Django migrations.AddField中外键的默认值

eel*_*oss 8 django default foreign-keys django-migrations

使用迁移,我需要向模型添加新字段(外键).我知道可以用:

    migrations.AddField(
        model_name='MyModel',
        name='state',
        field=models.ForeignKey(null=True, related_name='mymodel_state', to='msqa_common.MyModelState'),
    ),
Run Code Online (Sandbox Code Playgroud)

但是,我不希望我的字段可以为空.相反,我想使用它的默认值,对应于名称为"available"的MyModelState的id(id值可能在不同的机器中更改).表MyModelState的此"可用"值将在先前的迁移脚本中插入到数据库中,因此它确实存在.

我想我应该这样做:

    migrations.AddField(
        model_name='MyModel',
        name='state',
        field=models.ForeignKey(null=False, default=available_state_id, related_name='mymodel_state', to='msqa_common.MyModelState'),
    ),
Run Code Online (Sandbox Code Playgroud)

我的问题:我怎样才能获得available_state_id我的迁移脚本?

Dan*_*man 20

你不能直接这样做.建议的方法是创建一个迁移,使用null = True添加它,然后添加一个数据迁移,使用Python或SQL更新所有现有的指向available_state_id,然后是第三次迁移,将其更改为null =假.

  • https://docs.djangoproject.com/en/1.9/howto/writing-migrations/#migrations-that-add-unique-fields (3认同)

Be *_*Too 6

我只是遇到了同样的问题,偶然发现了这个答案,所以这是我的做法:

  operations = [
        # We are forced to create the field as non-nullable before
        # assigning each Car to a Brand
        migrations.AddField(
            model_name="car",
            name="brand",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                to="model.Brand",
            ),
        ),

        # assign_car_to_brand loops over all my Car objects and sets their
        # "brand" field
        migrations.RunPython(add_category_to_tags, do_nothing),

        # Make the field non-nullable to force all future Car to have a Brand
        migrations.AlterField(
            model_name="car",
            name="brand",
            field=models.ForeignKey(
                null=False,
                on_delete=django.db.models.deletion.PROTECT,
                to="model.Brand",
            ),
            preserve_default=False
        ),

    ]
Run Code Online (Sandbox Code Playgroud)