Mark
Mark

Reputation: 5499

Django South Migration does not work the first time around

I'm running a South migration python manage.py syncdb; python manage.py migrate --all which breaks when run on a fresh database. However, if you run it twice, it goes through fine! On the first try, I get

DoesNotExist: ContentType matching query does not exist. Lookup parameters were {'model': 'mymodel', 'app_label': 'myapp'}

After failure, I go into the database select * from django_content_type but sure enough it has

13 | my model     | myapp      | mymodel  

Then I run the migration python manage.py syncdb; python manage.py migrate --all and it works!

So how did I manage to make a migration that only works the second time around? By the way this is a data migration which puts the proper groups into the admin app. The following method within the migration is breaking it:

@staticmethod
def create_admin_group(orm, model_name, group_name):
    model_type = orm['contenttypes.ContentType'].objects.get(app_label='myapp', model=model_name.lower())
    permissions = orm['auth.Permission'].objects.filter(content_type=model_type)
    group = orm['auth.Group']()
    group.name = group_name
    group.save()
    group.permissions = permissions
    group.save()

(The migration files come from an existing working project which means a long time ago I had already run schemamigration --initial. I'm merely trying to replicate the database schema and initial data onto a new database.)

Upvotes: 3

Views: 3119

Answers (3)

Mark
Mark

Reputation: 5499

Turns out this is a bug in South.

http://south.aeracode.org/ticket/1281

Upvotes: 3

Paulo Bu
Paulo Bu

Reputation: 29794

It's a bad practice to issue python manage.py syncdb; python manage.py migrate --all for the first time. First of all, I won't trust much in --all option. It may include Django's oficial libraries and you certainly don't want that, even when There's nothing to migrate in them. I rather go by python manage.py migrate <app_name1> <app_name2> ...

But for what South concerns, the way of using South is:

  1. Create an app
  2. Create a migration for it with python manage.py schemamigration --initial <app>
  3. Convert to south and exising migration with python manage.py convert_to_south <app> --auto
  4. Do some modifications to the app and then python manage.py migrate <app>

Your approach might actually work, but take into account that when you do migrate --all you don't controll the order of migrations applied, and python manage.py syncdb won't assure the contentType your accessing is (myapp, mymodel) available at that time.

The error is appearing only first time because maybe the migration is actually being applied once. And getting save in the south_migrationhistory table as already applied, so when you issue the command again, it ignores it.

My advice, migrate first the target apps, after the syncdb command. If this doesn't work or things get messy, try this:

  1. Comment the line 'south', in INSTALLED_APPS
  2. Issue python manage.py syncdb
  3. Remove comment from line #'south', in INSTALLED_APPS
  4. Issue the final command python manage.py migrate --all

Good luck, hope this helps!

Upvotes: 1

Nafiul Islam
Nafiul Islam

Reputation: 82440

Of course its going to be like this, you have not made any intial schemamigrations. The right way would be like this:

  1. Register your django apps with south first. So something like:
    python manage.py schemamigration --initial <app_name>.
  2. Then you run manage.py syncdb.
  3. After this, you run migrate like so python manage.py migrate <apps>, please note that simply running migrate will just migrate all your registered apps. I tend to do this.
  4. If you change models to change the schema, then you can simply use:
    manage.py schemamigration --auto

The problem that you are alluding to is this. Once you run syncdb, you already get a table crated, south had nothing to do with this. What you are hence doing is querying a database that has no migration control (iirc).

Upvotes: 1

Related Questions