在迁移中添加django管理员权限:不存在权限匹配查询

时间:2015-07-30 22:18:17

标签: django django-migrations django-permissions

我想在手动编写的迁移中添加一些组并为其分配权限,但如果我在干净的数据库上运行它,则只有在运行所有迁移后才会创建权限。

我找到了这张票:https://code.djangoproject.com/ticket/23422 但我不能在那里发表评论(我可能会在表达对GeoDjango文档的不满之后被禁止),所以我将在下面的解决方案中分享一些改进。

5 个答案:

答案 0 :(得分:21)

在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

答案 1 :(得分:8)

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),
    ]

答案 2 :(得分:3)

如果你想要一些适用于任何版本的东西(或者在升级时会继续工作):

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

答案 3 :(得分:1)

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.")


答案 4 :(得分:0)

尝试在迁移期间获取权限会导致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'),可以遍历所有权限并按代号选择合适的权限。