如何在Django ImportExportModelAdmin中实现不存在关联对象自动创建
实现步骤
首先你原有代码里存在一个字段配置错误:email字段的attribute参数写为了email,但Investment模型本身没有该字段,会先触发属性不存在的报错,需要先修正该配置。
你可以通过重写InvestmentResource的before_save_instance钩子方法,在保存导入的Investment数据前自动处理关联Profile的创建/更新逻辑,具体修改后的代码如下:
class InvestmentResource(resources.ModelResource): # 保留原有字段配置用于导出功能,导入逻辑不再依赖ForeignKeyWidget的关联查找 firstname = fields.Field(attribute='profile', widget=ForeignKeyWidget(Profile, field='firstname'), column_name='firstname') lastname = fields.Field(attribute='profile', widget=ForeignKeyWidget(Profile, field='lastname'), column_name='lastname') # 修正attribute为profile,匹配Investment的关联字段 email = fields.Field(attribute='profile', widget=ForeignKeyWidget(Profile, field='email'), column_name='email') # 新增导入前的钩子方法处理Profile自动创建 def before_save_instance(self, instance, row, **kwargs): # 从当前导入的行数据中提取Profile的三个字段 email = row["email"] firstname = row["firstname"] lastname = row["lastname"] # 以唯一字段email为查询条件,不存在则创建,存在则更新姓名 profile, _ = Profile.objects.update_or_create( email=email, defaults={ "firstname": firstname, "lastname": lastname } ) # 将处理好的Profile实例关联到当前的Investment对象 instance.profile = profile # 执行父类原有保存逻辑 return super().before_save_instance(instance, row, **kwargs) class Meta: model = Investment fields = ( 'firstname', 'lastname', 'email', 'invested',) export_order = fields
逻辑说明
- 因为
Profile的email字段设置了唯一约束,所以我们用邮箱作为update_or_create的查询条件,保证不会生成重复的Profile数据 - 导入时不再依赖
ForeignKeyWidget的关联查找逻辑,避免关联对象不存在时报错 - 原有导出功能不受影响,仍然可以正常导出关联Profile的姓名字段
内容的提问来源于stack exchange,提问作者Prosy A.
相关产品推荐
相关产品推荐

