Почему я не могу назначить новое разрешение для группы в той же миграции в Django - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь добавить новые миграции, следуя этому учебнику Я добавил новое разрешение внутри Meta в поле permissions. Затем я создал миграцию и попытался изменить эту миграцию, чтобы обновить групповые разрешения на месте. Но получил DoesNotExist в RunPython операции.

from django.db import migrations


def assign_new_permission(apps, *args):
    Permission = apps.get_model('auth.Permission')
    Group = apps.get_model('auth.Group')
    # __fake__.DoesNotExist: Permission matching query does not exist.
    new_permission = Permission.objects.get(
        codename='my_new_permissoin_code')

    admins = Group.objects.get(name='Group name')
    admins.permissions.add(new_permission)


class Migration(migrations.Migration):
    dependencies = [
        ('my_app', '0066_some_migratoin'),
    ]

    operations = [
        migrations.AlterModelOptions(
            name='my_model',
            options={'permissions': (('my_new_permissoin_code',
                                      'Permission name'),)},
        ),
        migrations.RunPython(assign_new_permission)
    ]

1 Ответ

0 голосов
/ 03 августа 2018

Я думаю, что ваша проблема возникает из-за того, что разрешения на самом деле не создаются во время или после отдельной миграции, а запускаются сигналом после миграции, который отправляется после успешного завершения команды python manage.py migrate (см. Комментарии к принятому ответу здесь .)

Есть несколько способов обойти это:

  1. Разделите его на две отдельные миграции (создайте разрешения и затем назначьте их) и запустите их с помощью двух отдельных команд python manage.py migrate:

    python manage.py migrate my_app 0066_create_permissions
    python manage.py migrate my_app 0067_assign_permissions
    

    Это позволяет отправлять сигнал после миграции после запуска 0066 для создания разрешений.

  2. Разделите его на два этапа в рамках одной миграции, но вам придется вручную создать разрешения с помощью функции Python, а затем назначить их в другом. Вам придется изменить operations, чтобы учесть это. Одним из преимуществ этого является то, что при желании вы можете создать функцию или функции Python, чтобы также обратить миграцию, что на самом деле невозможно для # 3 или # 4.

  3. Издайте сигнал после миграции самостоятельно во время миграции. Это хорошее решение для случаев, когда вам нужны разрешения от сторонних приложений (например, django-guardian, как в моем примере), чтобы вы могли применять их при переносе данных.

    from django.apps import apps as django_apps
    def guardian_post_migrate_signal(apps, schema_editor):
        guardian_config = django_apps.get_app_config('guardian')
        models.signals.post_migrate.send(
            sender=guardian_config,
            app_config=guardian_config,
            verbosity=2,
            interactive=False,
            using=schema_editor.connection.alias,
        )
    
  4. Это похоже на # 3, но немного проще. Есть, вероятно, тонкие способы, которыми это лучше или хуже, но я не уверен, что они есть. Вы можете создать функцию, которая вызывает django.contrib.auth.management.create_permissions (кредит этой записи ) и использовать ее непосредственно при миграции:

    from django.contrib.auth.management import create_permissions
    
    def create_perms(apps, schema_editor):
        for app_config in apps.get_app_configs():
            app_config.models_module = True
            create_permissions(app_config, apps=apps, verbosity=0)
            app_config.models_module = None
    

    Тогда ваш operations будет выглядеть так:

        operations = [
            migrations.AlterModelOptions(
                name='my_model',
                options={'permissions': (('my_new_permissoin_code', 'Permission name'),)},
            ),
            migrations.RunPython(create_permissions),
            migrations.RunPython(assign_new_permission)
        ]
    

В любом случае, надеюсь, это поможет. Извините за информационную перегрузку - у меня была та же проблема, что и у вас в прошлом, и это заставило меня вернуться на несколько дней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...