Django重写模型save()方法后数据迁移时table_fields为空如何解决
问题原因
- 迁移操作中通过
apps.get_model()获取的是迁移快照里的历史版本模型,不会加载你在models.py中自定义的save()方法、类常量等业务逻辑 - 你使用的
bulk_create批量插入方法本身不会触发单个模型实例的save()方法,所以写在save中的默认值赋值逻辑完全没有执行
修复方案
方案1:修改迁移文件的数据生成逻辑
直接在迁移的make_report_fields函数中手动定义字段映射、给每个实例赋值table_fields,不需要依赖模型层的逻辑,修改后的迁移函数代码如下:
def make_report_fields(apps, schema_editor): User = apps.get_model(settings.AUTH_USER_MODEL) Report = apps.get_model('deal', 'Report') # 直接在迁移逻辑里定义字段映射 DEFAULT_TABLE_FIELDS = { 'OrderTrendReport': ('card', 'board', 'customer', 'amount', 'currency', 'stage', 'owner', 'country', 'local_ordered_date', 'local_delivery_deadline', 'order_number'), 'RevenueTrendReport': ('card', 'customer', 'invoice_total', 'payment_total', 'balance', 'currency', 'owner', 'order_number', 'board'), 'DealSuccessRateReport': ('card', 'board', 'customer', 'amount', 'currency', 'owner', 'result', 'local_result_updated_at'), 'DealLostReasonReport': ('card', 'board', 'customer', 'amount', 'currency', 'owner', 'local_result_updated_at', 'lost_reason', 'lost_description'), 'OrderByCategoryReport': ('card', 'board', 'customer', 'amount', 'currency', 'stage', 'owner', 'country', 'local_ordered_date', 'local_delivery_deadline', 'order_number') } ReportTypes = DEFAULT_TABLE_FIELDS.keys() report_fields = [ Report( user=user, report_type=report_type, # 直接赋值对应字段列表,转为list适配ArrayField格式 table_fields=list(DEFAULT_TABLE_FIELDS[report_type]) ) for report_type in ReportTypes for user in User.objects.all() ] Report.objects.bulk_create(report_fields)
如果已经执行过该迁移,先运行python manage.py migrate deal 0059回滚到上一个版本,修改迁移文件后再重新执行迁移即可。
方案2:(可选)优化模型层逻辑
你现有写在save中的逻辑在普通单实例保存场景下可以正常生效,但如果后续用到bulk_create、QuerySet.update等批量操作时还是不会触发save逻辑,需要在这类操作时手动给table_fields赋值即可。
内容的提问来源于stack exchange,提问作者Nick An
相关产品推荐
相关产品推荐

