我正试图使用Django -导入导出包(v3.0.0b4),通过Django Admin将csv文件(utf-8编码)导入Django模型。我最初使用的是上一个稳定版本,但鼓励我尝试预发行版。导入预览看起来是正确的,但是接口显示了csv所有行的以下错误:
“非字段特定”不是有效的UUID。
我尝试过在import_id_fields中包括'id‘或排除'id’字段,并使用重命名的'unique_id‘字段作为挂钩。我还尝试在csv的'id‘列和'unique_id’列中使用空白条目进行导入。同样,从csv中完全省略id字段。由于某种原因,无论我是否填充id字段,都将返回一个空白字段。我怀疑我做了什么小小的错事,但我不清楚是什么。resources.py、models.py和admin.py包括在下面。如果需要的话,很乐意分享其他片段。
models.py
from django.db import models
from django.db.models import Sum
import uuid
from datetime import datetime
class Purchase(models.Model):
id = models.UUIDField(primary_key=True,default=uuid.uuid4, editable=False)
date = models.DateField(blank=True,null=True)
seller = models.CharField(max_length=200,default='')
number = models.CharField(max_length=200,blank=True,default='')
customer = models.CharField(max_length=200,default='')
salesperson = models.CharField(max_length=200,blank=True,default='')
discount = models.FloatField(blank=True,default=0,null=True)
shipping = models.FloatField(blank=True,default=0,null=True)
tax = models.FloatField(blank=True,default=0,null=True)
file = models.FileField(blank=True,default='', upload_to='uploads/')
@property
def subtotal(self):
return LineItem.objects.filter(Purchase=self).aggregate(Sum('amount'))['amount__sum']
@property
def grand_total(self):
return round(self.subtotal+self.tax,2)
class Meta:
verbose_name_plural = "Purchases"
def __str__(self):
return self.seller+" "+self.number
class LineItem(models.Model):
id = models.UUIDField(primary_key=True,default=uuid.uuid4, editable=False)
purchase = models.ForeignKey(Purchase, on_delete= models.CASCADE, related_name="LineItem",default='',null=True)
product_id = models.CharField(max_length=200,blank=True,default='')
name = models.CharField(max_length=200,default='')
category = models.CharField(max_length=200,blank=True,default='')
qty = models.FloatField(null=True)
qty_uom = models.CharField(max_length=200,default='')
amount = models.FloatField(null=True)
pack_qty = models.FloatField(null=True)
pack_uom = models.CharField(max_length=200,default='')
@property
def date(self):
return format(self.purchase.date,f"%m/%d/%Y")
@property
def bulk_unit_price(self):
return round(self.amount/self.qty,2)
@property
def unit_price(self):
return round(self.bulk_unit_price/self.pack_qty,2)
class Meta:
verbose_name_plural = "LineItems"
def __str__(self):
return self.name
resources.py
from import_export import resources, widgets, fields
from django.db.models.query import *
from .models import LineItem, Purchase
class CharRequiredWidget(widgets.CharWidget):
def clean(self, value, row=None, *args, **kwargs):
val = super().clean(value)
if val:
return val
else:
raise ValueError('this field is required')
class FloatWidget(widgets.DecimalWidget):
def clean (self, value, row=None, *args, **kwargs):
if self.is_empty(value):
return None
return float(str(value))
class ForeignKeyWidgetWithCreation(widgets.ForeignKeyWidget):
def __init__(self, model, field="pk", create=False, **kwargs):
self.model = model
self.field = field
self.create = create
super(ForeignKeyWidgetWithCreation, self).__init__(model, field=field, **kwargs)
def clean(self, value, **kwargs):
if not value:
return None
if self.create:
self.model.objects.get_or_create(**{self.field: value})
val = super(ForeignKeyWidgetWithCreation, self).clean(value, **kwargs)
return self.model.objects.get(**{self.field: val}) if val else None
class LineItemResource(resources.ModelResource):
class Meta:
model = LineItem
import_id_fields = ['unique_id',]
exclude = ('id',)
fields = ('unique_id','purchase__seller','purchase__number','purchase__date','product_id','name','category','qty','qty_uom','amount','pack_qty','pack_uom',)
report_skipped = True
unique_id = fields.Field(column_name='unique_id', attribute='id',widget=CharRequiredWidget())
purchase__seller = fields.Field(attribute='purchase', widget=ForeignKeyWidgetWithCreation(model=Purchase,field='seller',create=True))
purchase__number = fields.Field(attribute='purchase', widget=ForeignKeyWidgetWithCreation(model=Purchase,field='number',create=True))
purchase__date = fields.Field(attribute='purchase',widget=ForeignKeyWidgetWithCreation(model=Purchase,field='date',create=True))
product_id = fields.Field(saves_null_values=False, attribute='product_id',widget=CharRequiredWidget())
name = fields.Field(saves_null_values=False, attribute='name',widget=CharRequiredWidget())
category = fields.Field(saves_null_values=False, attribute='category',widget=CharRequiredWidget())
qty = fields.Field(saves_null_values=False, attribute='qty',widget=FloatWidget())
qty_uom = fields.Field(saves_null_values=False, attribute='qty_uom',widget=CharRequiredWidget())
amount = fields.Field(saves_null_values=False, attribute='amount',widget=FloatWidget())
pack_qty = fields.Field(saves_null_values=False, attribute='pack_qty',widget=FloatWidget())
pack_uom = fields.Field(saves_null_values=False, attribute='pack_uom',widget=CharRequiredWidget())
admin.py
from django.contrib import admin
from django.contrib import admin
from .models import Purchase, LineItem
from .resources import LineItemResource
from django.db import models
from import_export.admin import ImportExportModelAdmin
class LineItemAdmin(ImportExportModelAdmin):
resource_class = LineItemResource
list_display = ('id','purchase','product_id','name','category','qty','qty_uom','amount','pack_qty','pack_uom',)
admin.site.register(Purchase)
admin.site.register(LineItem, LineItemAdmin)
csv结构:
id,unique_id,purchase__date,purchase__seller,purchase__number,product_id,name,category,amount,qty,qty_uom,unit_price,pack_qty,pack_uom,$/unit
,4e157e12-9a92-e303-44af-ee494593f073,4/29/2022,Vendor 1, 1423840,733111,item 1, category 1, 153.92,9.65,lb,15.95,1,lb,15.95
错误:
Exception in thread django-main-thread:
Traceback (most recent call last):
File "\mysite\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 187, in __get__
rel_obj = self.field.get_cached_value(instance)
File "\mysite\venv\lib\site-packages\django\db\models\fields\mixins.py", line 15, in get_cached_value
return instance._state.fields_cache[cache_name]
KeyError: 'purchase'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "\mysite\venv\lib\site-packages\django\db\models\fields\__init__.py", line 2614, in to_python
return uuid.UUID(**{input_form: value})
File "\lib\uuid.py", line 177, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "\lib\threading.py", line 973, in _bootstrap_inner
self.run()
File "\lib\threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "\mysite\venv\lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
fn(*args, **kwargs)
File "\mysite\venv\lib\site-packages\django\core\management\commands\runserver.py", line 125, in inner_run
autoreload.raise_last_exception()
File "\mysite\venv\lib\site-packages\django\utils\autoreload.py", line 87, in raise_last_exception
raise _exception[1]
File "\mysite\venv\lib\site-packages\django\core\management\__init__.py", line 398, in execute
autoreload.check_errors(django.setup)()
File "\mysite\venv\lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
fn(*args, **kwargs)
File "\mysite\venv\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "\mysite\venv\lib\site-packages\django\apps\registry.py", line 125, in populate
app_config.ready()
File "\mysite\venv\lib\site-packages\django\contrib\admin\apps.py", line 27, in ready
self.module.autodiscover()
File "\mysite\venv\lib\site-packages\django\contrib\admin\__init__.py", line 50, in autodiscover
autodiscover_modules("admin", register_to=site)
File "\mysite\venv\lib\site-packages\django\utils\module_loading.py", line 58, in autodiscover_modules
import_module("%s.%s" % (app_config.name, module_to_search))
File "\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "\mysite\main\admin.py", line 6, in <module>
from .resources import LineItemResource
File "\mysite\main\resources.py", line 175, in <module>
result = resource.import_data(
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 809, in import_data
return self.import_data_inner(
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 867, in import_data_inner
raise row_result.validation_error
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 707, in import_row
diff = self.get_diff_class()(self, original, new)
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 241, in __init__
self.left = self._export_resource_fields(resource, instance)
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 262, in _export_resource_fields
return [resource.export_field(f, instance) if instance else "" for f in resource.get_user_visible_fields()]
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 262, in <listcomp>
return [resource.export_field(f, instance) if instance else "" for f in resource.get_user_visible_fields()]
File "\mysite\venv\lib\site-packages\import_export\resources.py", line 920, in export_field
return field.export(obj)
File "\mysite\venv\lib\site-packages\import_export\fields.py", line 122, in export
value = self.get_value(obj)
File "\mysite\venv\lib\site-packages\import_export\fields.py", line 87, in get_value
value = getattr(value, attr, None)
File "\mysite\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 205, in __get__
rel_obj = self.get_object(instance)
File "\mysite\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 168, in get_object
return qs.get(self.field.get_reverse_related_filter(instance))
File "\mysite\venv\lib\site-packages\django\db\models\query.py", line 482, in get
clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
File "\mysite\venv\lib\site-packages\django\db\models\query.py", line 1071, in filter
return self._filter_or_exclude(False, args, kwargs)
File "\mysite\venv\lib\site-packages\django\db\models\query.py", line 1089, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "\mysite\venv\lib\site-packages\django\db\models\query.py", line 1096, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "\mysite\venv\lib\site-packages\django\db\models\sql\query.py", line 1502, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "\mysite\venv\lib\site-packages\django\db\models\sql\query.py", line 1532, in _add_q
child_clause, needed_inner = self.build_filter(
File "\mysite\venv\lib\site-packages\django\db\models\sql\query.py", line 1358, in build_filter
return self._add_q(
File "\mysite\venv\lib\site-packages\django\db\models\sql\query.py", line 1532, in _add_q
child_clause, needed_inner = self.build_filter(
File "\venv\lib\site-packages\django\db\models\sql\query.py", line 1448, in build_filter
condition = self.build_lookup(lookups, col, value)
File "\mysite\venv\lib\site-packages\django\db\models\sql\query.py", line 1273, in build_lookup
lookup = lookup_class(lhs, rhs)
File "\mysite\venv\lib\site-packages\django\db\models\lookups.py", line 27, in __init__
self.rhs = self.get_prep_lookup()
File "\mysite\venv\lib\site-packages\django\db\models\lookups.py", line 85, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "\mysite\venv\lib\site-packages\django\db\models\fields\__init__.py", line 2598, in get_prep_value
return self.to_python(value)
File "\mysite\venv\lib\site-packages\django\db\models\fields\__init__.py", line 2616, in to_python
raise exceptions.ValidationError(
django.core.exceptions.ValidationError: ['“” is not a valid UUID.']
发布于 2022-06-08 05:56:09
乍一看,有一个空的id
字段似乎是相关的(尽管您说您试图省略这个字段)。您可以尝试从id
和csv中删除对Resource
的所有引用,尽管您需要保持unique_id
声明的原样。
您还可以在调试期间尝试使用ForeignKeyWidget
而不是ForeignKeyWidgetWithCreation
。
您可以尝试通过脚本导入,而不是通过管理控制台。例如:
with open('data.csv', 'r') as fh:
dataset = tablib.Dataset().load(fh)
resource = LineItemResource()
result = resource.import_data(
dataset,
raise_errors=True
)
print(result)
这可能会帮助您理解错误,尽管识别错误的最快方法是使用调试器。
您还可以尝试使用2.8.1版本来查看这是否会产生影响(如果这已经在v3中引入)。
如果您可以在django-导入-导出示例应用程序中复制它,那将是非常有趣的。在release-3-x
分支中,有一个名为UUIDBook
的测试模型。如果您可以使用示例应用程序复制它,请提出一个问题,我们可以看看。
如果您发现错误的来源,请回发。
https://stackoverflow.com/questions/72539525
复制相似问题