Django: Providing initial group with migrations

1.4k views Asked by At

Since the using of an initial_data fixture is deprecated, I'm trying to add initial data with a migration.

I created my models, and one of the models contains a permission code-named can_use_feature.

When I run a makemigrations, a 0001_initial.py migration is created. The migrate command creates the database, well populated and the permission from above is in the auth_permission table.

Now I want to have a group with that permission by default in the database, so I create this migration as 0002_default_group.py:

from __future__ import unicode_literals
from django.db import migrations


def create_default_group(apps, schema_editor):

    GroupModel = apps.get_model('auth', 'group')

    group = GroupModel(name='My Group')
    group.save()

    PermissionModel = apps.get_model('auth', 'permission')
    permission = PermissionModel.objects.get(codename='can_use_feature')
    group.permissions.add(permission)


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(create_default_group),
    ]

Now something mysterious happens: When I delete the database again and execute the migrate command, an DoesNotExist error is raised, right at the permission = PermissionModel.objects.get(codename='can_use_feature') line.

When I remove the 0002_default_group.py, delete the database, execute migrate, copy the 0002_default_group.py back and run migrate again, everything works fine and the group is created in the way I want it.

What must be changed in order to get the migration to work in only one step?

1

There are 1 answers

2
knbk On

Permissions are created when the post_migrate signal fires. This signal is only fired if all migrations in the current run are completed. You cannot depend on the permissions existing within your migration.

The signal receiver that creates the permissions checks for existing permissions, so you can simply create the permission yourself if it doesn't exist yet.

It would also be good to add a dependency on ('auth', '__latest__') to ensure that the migrations for the Permission model have run and at least the table exists.