在迁移中添加 django 管理员权限:权限匹配查询不存在
Adding django admin permissions in a migration: Permission matching query does not exist
我想在手动编写的迁移中添加一些组并为它们分配权限,但如果我 运行 它在干净的数据库上,它只会在 运行 完成所有迁移后创建权限。
我找到了这张票:https://code.djangoproject.com/ticket/23422
但我不能在那里发表评论(我可能在表达了对 GeoDjango 文档的不满后被禁止了),所以我将在下面分享对解决方案的改进。
Django <= 1.9
查看 Django 的另一个答案 1.10+
调用create_permissions
就够了:
from django.contrib.auth.management import create_permissions
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
整个迁移过程是这样的
# coding:utf-8
from django.db import migrations
from django.contrib.auth.models import Permission, Group
from django.contrib.auth.management import create_permissions
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
MODERATORS_PERMISSIONS = ['change_modelname', ]
def add_permissions(apps, schema_editor):
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
moderators_group = Group.objects.get_or_create(
name=settings.MODERATORS_GROUP)[0]
for codename in MODERATORS_PERMISSIONS:
permission = Permission.objects.get(codename=codename)
moderators_group.permissions.add(permission)
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('thisappname', '0001_initial'),
]
operations = [
migrations.RunPython(add_permissions),
]
在 django 1.10 中可以使用以下代码:
from django.contrib.auth.management import create_permissions
def migrate_permissions(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
如果您想要可以在任何版本上运行的东西(或者在您升级后仍然可以运行的东西):
from django.contrib.auth.management import create_permissions
version = django.VERSION
if version[0] >= 1 and django.VERSION[1] > 9:
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
else:
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
在迁移期间尝试获取权限导致 Django 出现异常(权限匹配查询不存在)。这是 Django 中的一个老问题。
在 1.6 version
中,我通过 @int_ua's
片段解决了它,但在 1.11 version
中它不起作用(我不确定为什么)。
我在 1.11 version
中使用了这个解决方法:
def _assign_group_permissions(permission_codenames, apps, group_name):
permission_list = []
Permission = apps.get_model('auth', 'Permission')
for permission_codename in permission_codenames:
for permission in Permission.objects.all():
if permission.codename == permission_codename:
permission_list.append(permission)
Group = apps.get_model('auth', 'Group')
group = Group.objects.get(name=group_name)
group.permissions.add(*permission_list)
可以遍历所有权限并按代码名选择合适的权限,而不是 Permission.objects.get(codename='your_code_name')
。
Django 3.2
这是 Django 3.2 的版本,您可以从命令行运行:
./manage.py fix_permissions
# app_label/management/commands/fix_permissions.py
from django.contrib.auth.models import Permission
from django.contrib.auth.management import create_permissions
from django.core.management.base import BaseCommand
from django.apps import apps
class Command(BaseCommand):
help = 'Recreate permissions from scratch'
def handle(self, *args, **options):
# Run this method via shell whenever any amendments in any of the tables is made
print("Deleting existing user permissions...")
Permission.objects.all().delete()
for app_config in apps.get_app_configs():
print(f"Adding user permissions for {app_config}...")
app_config.models_module = True
create_permissions(app_config, apps=apps, verbosity=0)
app_config.models_module = None
print("DONE.")
我想在手动编写的迁移中添加一些组并为它们分配权限,但如果我 运行 它在干净的数据库上,它只会在 运行 完成所有迁移后创建权限。
我找到了这张票:https://code.djangoproject.com/ticket/23422 但我不能在那里发表评论(我可能在表达了对 GeoDjango 文档的不满后被禁止了),所以我将在下面分享对解决方案的改进。
Django <= 1.9
查看 Django 的另一个答案 1.10+
调用create_permissions
就够了:
from django.contrib.auth.management import create_permissions
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
整个迁移过程是这样的
# coding:utf-8
from django.db import migrations
from django.contrib.auth.models import Permission, Group
from django.contrib.auth.management import create_permissions
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
MODERATORS_PERMISSIONS = ['change_modelname', ]
def add_permissions(apps, schema_editor):
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
moderators_group = Group.objects.get_or_create(
name=settings.MODERATORS_GROUP)[0]
for codename in MODERATORS_PERMISSIONS:
permission = Permission.objects.get(codename=codename)
moderators_group.permissions.add(permission)
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('thisappname', '0001_initial'),
]
operations = [
migrations.RunPython(add_permissions),
]
在 django 1.10 中可以使用以下代码:
from django.contrib.auth.management import create_permissions
def migrate_permissions(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
如果您想要可以在任何版本上运行的东西(或者在您升级后仍然可以运行的东西):
from django.contrib.auth.management import create_permissions
version = django.VERSION
if version[0] >= 1 and django.VERSION[1] > 9:
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
else:
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
在迁移期间尝试获取权限导致 Django 出现异常(权限匹配查询不存在)。这是 Django 中的一个老问题。
在 1.6 version
中,我通过 @int_ua's
片段解决了它,但在 1.11 version
中它不起作用(我不确定为什么)。
我在 1.11 version
中使用了这个解决方法:
def _assign_group_permissions(permission_codenames, apps, group_name):
permission_list = []
Permission = apps.get_model('auth', 'Permission')
for permission_codename in permission_codenames:
for permission in Permission.objects.all():
if permission.codename == permission_codename:
permission_list.append(permission)
Group = apps.get_model('auth', 'Group')
group = Group.objects.get(name=group_name)
group.permissions.add(*permission_list)
可以遍历所有权限并按代码名选择合适的权限,而不是 Permission.objects.get(codename='your_code_name')
。
Django 3.2
这是 Django 3.2 的版本,您可以从命令行运行:
./manage.py fix_permissions
# app_label/management/commands/fix_permissions.py
from django.contrib.auth.models import Permission
from django.contrib.auth.management import create_permissions
from django.core.management.base import BaseCommand
from django.apps import apps
class Command(BaseCommand):
help = 'Recreate permissions from scratch'
def handle(self, *args, **options):
# Run this method via shell whenever any amendments in any of the tables is made
print("Deleting existing user permissions...")
Permission.objects.all().delete()
for app_config in apps.get_app_configs():
print(f"Adding user permissions for {app_config}...")
app_config.models_module = True
create_permissions(app_config, apps=apps, verbosity=0)
app_config.models_module = None
print("DONE.")