django-import-export按已有email更新Profile数据的导入报错求助
问题修复方案
错误根因
你遇到的报错来自三个错误用法:
- 重写
import_row方法后没有返回框架要求的RowResult对象,后续流程尝试访问返回对象的import_type属性时,触发了'NoneType' object has no attribute 'import_type'错误。 - 在
before_import_row中将行数据赋值给self的属性属于错误用法,ProfileResource实例在导入全程是复用的,批量导入时会出现多行行数据互相覆盖的问题。 - 配置的
import_id_fields = ('id', 'email')不符合需求,该配置会要求框架同时用id和email的组合匹配已有数据,无法实现仅靠email判断更新或创建的逻辑。
修复步骤
django-import-export本身已经内置了update_or_create逻辑,不需要手动实现,按以下步骤调整即可:
- 删除你自定义的
import_row方法,不需要手动调用Profile.objects.update_or_create - 修正
Meta配置中的import_id_fields,仅保留email作为匹配已有数据的唯一键 - 精简
before_import_row逻辑,仅保留必要的行数据处理,不需要把行值赋值给self属性
修正后的完整代码
class ProfileResource(resources.ModelResource): email = fields.Field( attribute='email', widget=CharWidget(), column_name='email' ) class Meta: model = Profile clean_model_instances = True # 仅用email作为唯一匹配键,框架自动实现存在则更新、不存在则新建逻辑 import_id_fields = ('email',) def before_import_row(self, row, row_number=None, **kwargs): # 仅处理空id的情况 try: if row["id"] == '': row["id"] = None except KeyError: pass
自定义import_row的正确写法(非必要不需要用)
如果确实需要重写import_row添加自定义逻辑,必须调用父类方法并返回对应的结果,示例如下:
import sys def import_row(self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs): try: # 你的自定义逻辑写在这里 # 必须调用父类方法获取标准返回结果 result = super().import_row( row, instance_loader, using_transactions=using_transactions, dry_run=dry_run, **kwargs ) except Exception as e: print(e, file=sys.stderr) raise # 必须返回RowResult对象 return result
内容的提问来源于stack exchange,提问作者Prosy A.
相关产品推荐
相关产品推荐

