Django库,用于快速导入CSV和其他结构化数据,使用Django的ModelForm进行验证并将数据反序列化到实例。
项目描述
django-model-import
Django Model Import是一个轻量级的CSV导入器,专为速度而构建。
它使用标准的 Django ModelForm
解析每一行,为您提供了熟悉的数据验证和模型实例化的 API。在大多数情况下,如果您已经有了您要导入的 ContentType
的 ModelForm
,您不需要创建特定的导入表单。
为了向正在运行导入的最终用户呈现反馈,您可以轻松地通过切换 commit
参数生成导入数据的预览。
它还提供了一些针对 ForeignKey 的导入优化字段,允许预加载所有可能的值,或者在查找发生时缓存每个查找,或者在需要多个字段来唯一标识资源的地方查找模型。
安装
poetry add django-model-import
快速入门
import djangomodelimport
class BookImporter(djangomodelimport.ImporterModelForm):
name = forms.CharField()
author = CachedChoiceField(queryset=Author.objects.all(), to_field='name')
class Meta:
model = Book
fields = (
'name',
'author',
)
with default_storage.open('books.csv', 'rb') as fh:
data = fh.read().decode("utf-8")
# Use tablib
parser = djangomodelimport.TablibCSVImportParser(BookImporter)
headers, rows = parser.parse(data)
# Process
importer = djangomodelimport.ModelImporter(BookImporter)
preview = importer.process(headers, rows, commit=False)
errors = preview.get_errors()
if errors:
print(errors)
importresult = importer.process(headers, rows, commit=True)
for result in importresult.get_results():
print(result.instance)
复合键查找
通常无法通过单个唯一字符串引用关系。为此,我们可以使用带 CompositeLookupWidget
的 CachedChoiceField
。小部件在源 CSV 的 type
和 variant
列下查找值,并使用在 to_field
中指定的字段名进行唯一查找,例如 queryset.get(type__name=type, name=variant)
。
每个 get
的结果都会在导入剩余过程中内部缓存,以最小化数据库访问。
class AssetImporter(ImporterModelForm):
site = djangomodelimport.CachedChoiceField(queryset=Site.objects.active(), to_field='ref')
type = djangomodelimport.CachedChoiceField(queryset=AssetType.objects.filter(is_active=True), to_field='name')
type_variant = djangomodelimport.CachedChoiceField(
queryset=InspectionItemTypeVariant.objects.filter(is_active=True),
required=False,
widget=djangomodelimport.CompositeLookupWidget(source=('type', 'variant')),
to_field=('type__name', 'name'),
)
contractor = djangomodelimport.CachedChoiceField(queryset=Contractor.objects.active(), to_field='name')
扁平相关字段
通常您将有一个 OneToOneField 或只是一个指向另一个模型的 ForeignKey,但您希望能够通过这个来创建/更新其他模型。您可以使用 FlatRelatedField
将相关模型的所有字段扁平化到这个导入器中。
class ClientImporter(ImporterModelForm):
primary_contact = FlatRelatedField(
queryset=ContactDetails.objects.all(),
fields={
'contact_name': {'to_field': 'name', 'required': True},
'email': {'to_field': 'email'},
'email_cc': {'to_field': 'email_cc'},
'mobile': {'to_field': 'mobile'},
'phone_bh': {'to_field': 'phone_bh'},
'phone_ah': {'to_field': 'phone_ah'},
'fax': {'to_field': 'fax'},
},
)
class Meta:
model = Client
fields = (
'name',
'ref',
'is_active',
'account',
'primary_contact',
)
测试
使用 python example/manage.py test testapp
运行测试