Django迁移默认值callable生成相同的条目

时间:2017-02-27 22:07:32

标签: django python-3.x django-migrations

我在现有的db表中添加了一个新字段。它是用字符串自动生成的。
这是我的代码:

from django.utils.crypto import get_random_string

...
Model:
    verification_token = models.CharField(max_length=60, null=False, blank=False, default=get_random_string)

我使用./manage.py makemigrations生成我的迁移文件,并生成一个文件。 我验证新文件的默认设置为field=models.CharField(default=django.utils.crypto.get_random_string, max_length=60)

所以一切似乎都很好。
继续./manage.py migrate,终端没有错误。 但是,当我查看我的表格时,我看到所有token字段都填充了相同的值 enter image description here

这是我做错了吗? 我如何在迁移中修复此问题?

2 个答案:

答案 0 :(得分:2)

如果将新列添加到表中,并且列为NOT NULL,则在创建列期间,列中的每个条目都必须填充有效值。 Django通过向列定义添加DEFAULT子句来实现此目的。由于这是整个列的单个默认值,因此只能调用一次函数。

您可以使用数据迁移使用唯一值填充列。描述了in the documentation略有不同的用例的过程,但数据迁移的基础知识如下:

from django.db import migrations, models
from django.utils.crypto import get_random_string

def generate_verification_token(apps, schema_editor):
    MyModel = apps.get_model('myapp', 'MyModel')
    for row in MyModel.objects.all():
        row.verification_token = get_random_string()
        row.save()

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0004_add_verification_token_field'),
    ]

    operations = [
        # omit reverse_code=... if you don't want the migration to be reversible.
        migrations.RunPython(generate_verification_token, reverse_code=migrations.RunPython.noop),
    ]

只需将其添加到新的迁移文件中,更改apps.get_model()调用并更改依赖关系以指向应用程序中的上一次迁移。

答案 1 :(得分:1)

它可能是要排序的标记字符串,因此django将保存一些重复值。但是,我不确定这是你的主要问题。

无论如何,我建议您使用while处理重复值,然后按生成的令牌过滤您的模型,以确保该令牌尚未使用。我会给你例如下面的例子。

from django.utils.crypto import get_random_string

def generate_token():
    token = get_random_string()
    number = 2
    while YourModel.objects.filter(verification_token=token).exists():
        token = '%s-%d' % (token, number)
        number += 1
    return token

verification_token;

的字段中
verification_token = models.CharField(max_length=60, unique=True, default=generate_token)

我还建议您使用unique=True来处理重复的值。