I just learnt how to do this with a single migration!
when running makemigrations
django should ask you to set a one-off default. Define whatever you can here to keep it happy, and you'll end up with the migration AddField
you mentioned.
migrations.AddField(
model_name='series',
name='updated_as',
field=models.DateTimeField(default=????, auto_now=True),
),
Change this one operation into 3 operations:
- initially make the field nullable, so the column will be added.
- call a function to populate the field as needed.
- alter the field (with
AlterField
) to make it not nullable (like the above, with no default).
so you end up with something like.
migrations.AddField(
model_name='series',
name='updated_as',
field=models.DateTimeField(null=True, auto_now=True),
),
migrations.RunPython(set_my_defaults, reverse_func),
migrations.AlterField(
model_name='series',
name='updated_as',
field=models.DateTimeField(auto_now=True),
),
with your functions defined as something like:
def set_my_defaults(apps, schema_editor):
Series = apps.get_model('myapp', 'Series')
for series in Series.objects.all().iterator():
series.updated_as = datetime.now() + timedelta(days=series.some_other_field)
series.save()
def reverse_func(apps, schema_editor):
pass # code for reverting migration, if any
Except, you know, not terrible; consider using F expressions and/or database functions to increase migration performance for large databases.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…