Search code examples
sqldjangomigrationdjango-southrelational

Django migrations/South: New column take default value another value from the same record


I want to add a new column to an already existing table, but I want to give it a default value dependent on already existing data:

e.g. Each record has a start_date. Now I want to add an open_until column, and I want to fill it with the value for start_date of each existing record. (the upcoming records will be able to pick different value)

Is there a friendly way to do this?


Solution

  • You can also do it within South. The only caveat is that you need two steps for that:

    1. A schema migration that adds the open_until column

      from django.db import models
      import datetime
      
      class MyModel(models.Model):
          start_date = models.DateField(),
          open_until = models.DateField(default=datetime.date.today),
      

      $ python manage.py schemamigration --auto appname

    2. A data migration that fills existing rows with the value of that other column

      $ python manage.py datamigration appname populate_open_until

      import datetime
      
      class Migration(DataMigration):
      
          def forwards(self, orm):
              "Set open_until value to that of start_date for existing rows"
              for t in orm.MyModel.objects.all():
                  t.open_until = t.start_date
                  t.save()
      
          def backwards(self, orm):
              "Revert back to default"
              for t in orm.MyModel.objects.all():
                  t.open_until = datetime.date.today
                  t.save()
      

    (optional) In step 1 you can either provide a temporary default value or make it optional and add a 3rd step

    1. A schema migration that makes the open_until column mandatory.