Я пытаюсь добавить новые миграции, следуя этому руководство
Я добавил новое разрешение внутри 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)
]





Я думаю, что ваша проблема возникает из-за того, что разрешения фактически не создаются во время или после отдельной миграции, а запускаются сигналом после миграции, который отправляется после успешного завершения команды 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_permission_code', 'Permission name'),)},
),
migrations.RunPython(create_perms),
migrations.RunPython(assign_perms)
]
В любом случае, я надеюсь, что это поможет. Извините за информационную перегрузку - у меня была та же проблема, что и у вас, в прошлом, и это отбросило меня на несколько дней.