2017-02-27 86 views
0

我正在添加一个新的字段到现有的数据库表。它是用字符串自动生成的。
这里是我的代码:Django迁移默认值可调用生成相同的条目

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

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

回答

1

当一个新列被添加到一个表中,并且该列为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()呼叫,改变依赖点到之前的应用程序迁移。

+0

我最终使用了这个,并用Django迁移清除了一些问题。谢谢, –

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来处理重复值。

+0

尽管由于django迁移而无法使用所有现有行的默认值,因此向我发送了正确的方向。 –