wKa*_*vey 13 python django database-migration python-3.x django-migrations
我有一个现有的模型,看起来有点像下面的......
class Resource(models.Model):
id = models.AutoField(primary_key=True)
Run Code Online (Sandbox Code Playgroud)
我们已经使用它有一段时间了,现在Resource我们的数据库中有大约 1M 个这些对象的实例(以及相关的foreignkey/else 用法)。
我现在需要跟踪该模型上的另一个 ID,我想要强制执行的 ID 是唯一的。
other_id = models.IntegerField(unique=True)
Run Code Online (Sandbox Code Playgroud)
此other_id信息当前存储在一些外部 CSV 中,我想(在此过程中的某个时刻)将此信息加载到所有现有Resource实例中。
添加上述字段后,Django 的makemigrations工作正常。但是,当我针对现有数据库应用所述迁移时,我收到一条错误,指示我需要提供默认值以用于所有现有Resource实例。相信很多人都见过类似的事情。
解决此限制的最佳方法是什么?我想到的一些方法...
unique=True要求other_id到所有现有模型(通过某些管理命令或 1-off 脚本)unique=True回来并应用迁移other_id值other_id在运行时自动引用这些外部 CSV 来加载值manage.py migrate。如果(在将来的某个时刻)有人重新运行这些迁移并且这部分失败(无法id在 CSV 中找到现有资源来提取other_id),这可能会遇到问题。所有这些感觉都很复杂,但我想我想做的也不是最简单的事情。
有任何想法吗?我不得不想象过去有人必须解决类似的问题。
谢谢!
bru*_*ers 16
实际上,问题的来源或问题本身并不是唯一约束,而是您的字段不允许空值并且没有默认值这一事实 - 对于非唯一字段,您会遇到同样的错误。
这里正确的解决方案是允许该字段为 null ( null=True) 并将其默认为None(这将转换为 sql“null”)。由于null值被排除在唯一约束之外(至少如果您的数据库供应商遵守 SQL 标准),这允许您应用架构更改,同时仍然确保您不能有非空值的重复项。
然后,您可能需要数据迁移来加载已知的“other_id”值,并最终进行第三次架构迁移以禁止此字段为空值 - 当且仅当您知道已为所有记录填充此字段时。
Mar*_*ind 11
Django 有一个叫做“数据迁移”的东西,您可以在其中创建一个迁移文件,在应用迁移时修改/删除/添加数据到数据库中。
在这种情况下,您将创建 3 个不同的迁移:
null=True。null=True。然后运行时,python manage.py migrate它将按正确的顺序应用步骤 1-3 中的所有迁移。
您的数据迁移将如下所示:
from django.db import migrations
def populate_reference(apps, schema_editor):
MyModel = apps.get_model('yourappname', 'MyModel')
for obj in MyModel.objects.all():
obj.other_id = random_id_generator()
obj.save()
class Migration(migrations.Migration):
dependencies = [
('yourappname', '0001_initial'),
]
operations = [
migrations.RunPython(populate_reference),
]
Run Code Online (Sandbox Code Playgroud)
您可以使用该命令创建一个空的迁移文件./manage.py makemigrations --empty yourappname。