Using migrations, I need to add a new field (a foreign key) to a model. I know it can be done with:
migrations.AddField(
model_name='MyModel',
name='state',
field=models.ForeignKey(null=True, related_name='mymodel_state', to='msqa_common.MyModelState'),
),
However, I don't want my field to be nullable. Instead, I want to use a default value for it, corresponding to the id of MyModelState whose name is "available" (id value might change in different machines). This "available" value of table MyModelState is inserted into the database in a previous migration script, so it does exist.
I guess I should do something like:
migrations.AddField(
model_name='MyModel',
name='state',
field=models.ForeignKey(null=False, default=available_state_id, related_name='mymodel_state', to='msqa_common.MyModelState'),
),
My question: How can I get the available_state_id
within my migration script?
You can't do it directly. The recommended way of doing this is to create a migration to add it with null=True, then add a data migration that uses either Python or SQL to update all the existing ones to point to available_state_id
, then a third migration that changes it to null=False.
I just had the same issue and stumbled upon this answer, so here is how I did it:
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
),
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With