Search code examples
djangodjango-south

write an advanced migration with south


I just added a field "is_capital" to my model "Realm" which has a foreign key pointing to "User".

this is what it looks like:

class Realm(models.Model):
    user = models.ForeignKey(User)
    is_capital = models.BooleanField( default=False ) #field not synced yet
    #...

By default, I want all the records per User to have the "is_capital" flag set to false, all BUT the first (or a random one). In the end there should be only one "realm" flagged "is_capital" per user.

So the table should look like this in the end:

Realm

realm_id ; user_id ; is_capital
1 ; 1 ; True
2 ; 1 ; False
3 ; 1 ; False
4 ; 2 ; True
5 ; 2 ; False

How can I do such a migration ? All examples I have seen are just filling the new columns with a single value.


Solution

  • Add a schemamigration to add the field with default=False.

    python manage.py schemamigration app_name --auto
    

    Run this migration.

    Then create a data migration for making your changes

    ./manage.py datamigration app_name mark_is_capital
    

    In your forwards() of created migration file, write:

    for user in orm.User.objects.all():
        realms = orm.Realm.objects.filter(user=user)
        if realms:
            realm_to_change = realms[0]
            realm_to_change.is_capital = True
            realm_to_change.save()