Почему я не могу назначить новое разрешение для группы в той же миграции в Django
Я пытаюсь добавить новые миграции, следуя этому руководству. Я добавил новое разрешение внутри 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 ответ
Я думаю, что ваша проблема возникает из-за того, что разрешения на самом деле не создаются во время или после отдельной миграции, а запускаются сигналом после миграции, который отправляется после python manage.py migrate
Команда успешно завершена (см. комментарии о принятом ответе здесь.)
Есть несколько способов обойти это:
Разделите его на две отдельные миграции (создайте разрешения и затем назначьте их) и запустите их с двумя отдельными
python manage.py migrate
команды:python manage.py migrate my_app 0066_create_permissions python manage.py migrate my_app 0067_assign_permissions
Это позволяет отправлять сигнал после миграции после запуска 0066 для создания разрешений.
Разделите его на два этапа в рамках одной миграции, но вам придется вручную создать разрешения с помощью функции Python, а затем назначить их в другом. Вам придется изменить свой
operations
чтобы объяснить это. Одним из преимуществ этого является то, что при желании вы можете создать функцию или функции Python, чтобы также обратить миграцию, что на самом деле невозможно для #3 или #4.Издайте сигнал после миграции самостоятельно во время миграции. Это хорошее решение для случаев, когда вам нужны разрешения от сторонних приложений (например, 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, )
Это похоже на № 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) ]
Во всяком случае, я надеюсь, что это помогает. Извините за информационную перегрузку - у меня была та же проблема, что и у вас в прошлом, и это заставило меня вернуться на несколько дней.