使用Django-import-export:如何通过before_import_row自动创建不存在对象?
解决Django-import-export自动创建关联对象的问题
要实现导入时自动创建不存在的Category对象,你只需要在QuestionResource中重写before_import_row方法,在每一行数据导入前检查对应的分类是否存在,不存在则创建即可。
下面是完整的实现代码:
from import_export import resources, fields from import_export.widgets import ForeignKeyWidget from .models import Question, Category class QuestionResource(resources.ModelResource): category = fields.Field( column_name='category', attribute='category', widget=ForeignKeyWidget(Category, 'category') ) def before_import_row(self, row, **kwargs): # 获取导入行中的category名称 category_name = row.get('category') if category_name: # 使用get_or_create:不存在则创建,存在则获取已有对象 category, created = Category.objects.get_or_create(category=category_name) # 将当前行的category字段替换为创建/获取到的对象主键 row['category'] = category.pk class Meta: model = Question fields = ['id', 'question', 'category', 'answer',] # exclude = ('created', 'modified', 'verified', 'count', 'user_created')
关键逻辑说明:
- 重写
before_import_row方法:这个方法会在每一行数据被处理前触发,刚好适合做前置检查和创建操作。 - 提取分类名称:从导入的行数据中取出
category列的值。 get_or_create的作用:这是Django ORM的便捷方法,会尝试根据category字段的值查找对象;如果找不到就自动创建一个新的Category实例,返回的元组里第一个是目标对象,第二个是标记是否新建的布尔值。- 替换行数据值:因为
ForeignKeyWidget最终需要关联对象的主键(pk),所以我们把行中的分类名称替换为刚创建/获取到的Category对象的pk,确保后续导入能正确关联。
额外注意:
- 建议给
Category模型的category字段设置unique=True,避免重复创建相同名称的分类。 - 代码里的
if category_name:判断是为了防止导入空值时创建无效分类,如果你允许空分类,可以去掉这个判断。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

