4

After seeing this post, I tried to create my own group at project setup with this migration :

from django.db import migrations
from django.contrib.auth.models import Group, Permission

def create_group(apps, schema_editor):
    group, created = Group.objects.get_or_create(name='thing_managers')
    if created:
        add_thing = Permission.objects.get(codename='add_thing')
        group.permissions.add(add_thing)
        group.save()

class Migration(migrations.Migration):

    dependencies = [
        ('main', '0002_auto_20160720_1809'),
    ]

    operations = [
        migrations.RunPython(create_group),
    ]

But I got the following error :

django.contrib.auth.models.DoesNotExist: Permission matching query does not exist.

Here is my model :

class Thing(models.Model):
    pass

Why can't I do that? How could I solve this?

I use django 1.9.

Community
  • 1
  • 1
vmonteco
  • 14,136
  • 15
  • 55
  • 86
  • First of all, you should not import your the models from `from django.contrib.auth.models import Group, Permission`, but using `apps.get_model("some_app", "model_name")`. And 2nd the error is pretty clear - you don't have a permission with `codename='add_thing'` – Todor Jul 20 '16 at 21:54

3 Answers3

2

Permissions are created in a post_migrate signal. They don't exist the first time migrations are run after a new model is added. It is probably easiest to run the post_migrate signal handler manually:

from django.contrib.auth.management import create_permissions

def create_group(apps, schema_editor):
    for app_config in apps.get_app_configs():
        create_permissions(app_config, apps=apps, verbosity=0)

    group, created = Group.objects.get_or_create(name='thing_managers')
    if created:
        add_thing = Permission.objects.get(codename='add_thing')
        group.permissions.add(add_thing)
        group.save()

create_permissions checks for existing permissions, so this won't create any duplicates.

knbk
  • 52,111
  • 9
  • 124
  • 122
  • But in this case, how was the answer to another post I linked supposed to work? Perhaps the permissions creation process changed since 1.7? I tried your solution but I still have the same error. – vmonteco Jul 20 '16 at 23:21
  • For which model are the permissions you're trying to fetch? Is the model created in the same app, in a previous migration? Otherwise you might have to [add a dependency](https://docs.djangoproject.com/en/1.9/topics/migrations/#accessing-models-from-other-apps) to the app where the model is defined. – knbk Jul 20 '16 at 23:27
  • For the `Thing` model in my `main` app. The model is created in the models.py file, I didn't touch to migrations before this. – vmonteco Jul 21 '16 at 00:15
2

From this Django ticket, here's what worked for me in Django 3.0.4 and apparently will work in >=1.9:

from django.core.management.sql import emit_post_migrate_signal

def create_group(apps, schema_editor):
    # Ensure permissions and content types have been created.
    db_alias = schema_editor.connection.alias
    emit_post_migrate_signal(2, False, db_alias)
    # Now the content types and permissions should exist

    Permission = apps.get_model('auth', 'Permission')
    ...
incidentist
  • 403
  • 5
  • 9
1

One solution is call the update_permissions command before try to append a permission

from django.core.management import call_command

def update_permissions(schema, group):
    call_command('update_permissions')


operations = [
        migrations.RunPython(update_permissions, reverse_code=migrations.RunPython.noop),
        migrations.RunPython(create_group),
    ]

And as was commented don't import Group and Permission models use:

Group = apps.get_model("auth","Group")
Permission = apps.get_model("auth","Permission")