我有一个现有的模型,看起来有点像下面这样......
class Resource(models.Model):
id = models.AutoField(primary_key=True)
我们已经使用它一段时间了,现在我们的数据库中有这些
Resource
对象(以及相关的 ForeignKey/else 用法)的大约 1M 个实例。我现在需要跟踪此模型上的另一个 ID,我想强制执行的 ID 是唯一的。
other_id = models.IntegerField(unique=True)
此
other_id
信息当前存储在一些外部 CSV 中,我想(在此过程中的某个时刻)将此信息加载到所有现有的 Resource
实例中。添加上述字段后,Django 的
makemigrations
工作正常。但是,当我对现有数据库应用所述迁移时,我收到一条错误消息,表明我需要提供一个默认值以用于所有现有 Resource
实例。相信很多人都见过类似的情况。解决此限制的最佳方法是什么?我想到的一些方法...
unique=True
要求 other_id
值从外部加载到所有现有模型(通过某些管理命令或 1-off 脚本) unique=True
并应用迁移 other_id
值 other_id
时自动引用这些外部 CSV 以加载 manage.py migrate
值。如果(在将来的某个时候)有人重新运行这些迁移并且这部分失败(无法在 CSV 中找到现有资源 id
以提取 other_id
),这可能会遇到问题。 所有这些都感觉很复杂,但话说回来,我想我想做的也不是最简单的事情。
有任何想法吗?我不得不想象过去有人不得不解决类似的问题。
谢谢!
最佳答案
实际上,来源或您的问题本身并不是唯一约束,而是您的字段不允许空值且没有默认值这一事实 - 对于非唯一字段,您会遇到相同的错误。
这里正确的解决方案是允许该字段为空( null=True
)并将其默认为 None
(这将转换为 sql "null")。由于 null
值被排除在唯一约束之外(至少如果您的数据库供应商遵守 SQL 标准),这允许您应用架构更改,同时仍然确保您不能有非空值的重复项。
然后,您可能需要数据迁移以加载已知的“other_id”值,并最终进行第三次架构迁移以禁止此字段的空值 - 当且仅当您知道已为所有记录填充此字段时。
关于python - 向现有 django 模型添加新的唯一字段时的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56934804/