Migrating with South on a field that uses auto_now_add=True
16th of December 2009
I have a Django model that looks something like this:
class MyModel(models.Model):
modify_date = models.DateTimeField(auto_now=True)
...
modify_date = models.DateTimeField(auto_now=True)
...
Retroactively now I wanted to add a field called add_date which uses the auto_now_add=True trick. The migration used in this project is South which is great but doesn't work very well with the auto_now_add=True because the field doesn't have a straight forward default. So, first I changed the field to this:
class MyModel(models.Model):
modify_date = models.DateTimeField(auto_now=True)
add_date = models.DateTimeField(auto_now_add=True, null=True)
...
modify_date = models.DateTimeField(auto_now=True)
add_date = models.DateTimeField(auto_now_add=True, null=True)
...
Notice the null=True which is important. Then I used startmigration to generate the code for the forward and backward to which I added a this stuff:
class Migration:
def forwards(self, orm):
db.add_column('myapp_mymodel', 'add_date', orm['myapp.mymodel:add_date'])
for each in MyModel.objects.all():
# since MyModel is referenced elsewhere I can work out the oldest date
oldest_date = get_oldest_related_date(each,
default=each.modify_date)
each.add_date = oldest_date
each.save()
def forwards(self, orm):
db.add_column('myapp_mymodel', 'add_date', orm['myapp.mymodel:add_date'])
for each in MyModel.objects.all():
# since MyModel is referenced elsewhere I can work out the oldest date
oldest_date = get_oldest_related_date(each,
default=each.modify_date)
each.add_date = oldest_date
each.save()
That way all old records will have the date (not entirely accurate but good enough) and all new records will automatically get a date. Is there a better way? I bet, but I don't know how to do it.