django - 如何在 Django 中从一组模型字段到另一组模型字段对 unique_together 约束进行更改
问题描述
在我的 Django 项目中,我有以下模型:
class TenderOrigin(models.Model):
doc_type = models.CharField(max_length=2, ...)
doc_short_txt = models.CharField(max_length=150, ...)
create_date = models.DateField(default=timezone.now, ...)
port_grp = models.ForeignKey(PortGroup, on_delete=models.CASCADE, null=True, ...)
# frt_grp = models.ForeignKey(FrtGroup, on_delete=models.CASCADE, null=True, ...)
locn_from = models.ForeignKey(Plant, on_delete=models.CASCADE, ...)
tender_number = models.CharField(max_length=150, null=True,...)
tender_date = models.DateField(null=True, ...)
class Meta:
ordering = ['locn_from__LocName']
# unique_together = [['frt_grp', 'locn_from', 'tender_date'],] # Original constraint
unique_together = [['port_grp', 'locn_from', 'tender_date'],] # New constraint being defined
如上所述(针对唯一约束的定义),我正在尝试将原始unique_together约束更改为新约束(使用 field port_grp
)。新字段 ( port_grp
) 需要进行更改,该字段被添加到模型中,而字段frt_grp
正在被删除。
但是,在迁移时,我收到以下错误消息:
...
...
Traceback (most recent call last):
File "manage.py", line 15, in <module>
execute_from_command_line(sys.argv)
...
...
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 303, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: matmovt_tenderorigin.port_grp_id, matmovt_tenderorigin.locn_from_id, matmovt_tenderorigin.tender_date
是否可以将针对一组字段定义的unique_together约束更改为另一组(不删除现有数据)?
解决方案
这就是我的处理方式。
- 根据需要在模型上创建新字段。
- 为新字段创建迁移。
- 创建数据迁移以填充新字段
- 创建 UniqueConstraint 并删除旧的唯一约束。
- 为约束更改生成迁移。确保放置在创建之后。虽然它应该全部在事务中运行,所以它应该无关紧要。
- 删除旧字段。
如果您的数据迁移将创建违反旧唯一约束的数据,则在进行数据迁移之前将其删除。显然这是非常危险的,因为现在您允许系统本身生成可能无效的数据,从而使回滚/反向迁移非常痛苦。