2017-02-27 2 views
0

私は既存のdbテーブルに新しいフィールドを追加します。それは文字列で自動生成されます。Djangoマイグレーションのデフォルト値callableは同じエントリを生成します

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句を追加することでこれを行います。これは列全体の単一のデフォルト値なので、関数は一度だけ呼び出されます。

データ移行を使用して、列に一意の値を設定できます。

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()コールを変更、新しい移行ファイルに以下を追加して指すように依存関係を変更します。次のようにわずかに異なるユースケースのための手順はin the documentationを説明するが、データ移行の基本は、アプリ内での以前の移行まで

+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の移行のために動作しませんでしたが、既存のすべての行に1つのデフォルト値を使用し、正しい方向に私を送りました。 –

関連する問題