Django-guardian: 在 Django 1.7 迁移中使用assign_perm

创建于 2014-11-13  ·  10评论  ·  资料来源: django-guardian/django-guardian

考虑以下迁移代码:

from django.db import models, migrations
from guardian.shortcuts import assign_perm

def assign_perms(apps, schema_editor):
    Group = apps.get_model("auth", "Group")
    for group in Group.objects.all():
        assign_perm('products.view_product', group)
        # assign_perm('products.view_product', group, product)

class Migration(migrations.Migration):

    operations = [
        migrations.RunPython(assign_perms),
    ]

应用此迁移时, assign_perm调用会出现错误:

guardian.exceptions.NotUserNorGroup: User/AnonymousUser or Group instance is required (got Group object)

最有用的评论

我在这里发布它,以防它对其他人有用,但我为初始设置迁移编写了这个相对通用的assign_perm方法,做了一些假设,但可能有帮助:

def assign_perm(perm, user_or_group, obj=None, apps=None):
    permission_model = apps.get_model('auth', 'Permission')
    permission = permission_model.objects.get(codename=perm)

    # Assumes object permission models live in the same app as the model they govern
    # and are named like `ProjectUserObjectPermission`/`ProjectGroupObjectPermission`
    obj_permission_model = apps.get_model(obj._meta.app_label, '{}{}ObjectPermission'.format(
        obj._meta.object_name,
        user_or_group._meta.object_name,
    ))
    obj_permission_model.objects.create(
        # `object_pk` and `content_type_id` keys if you're not using direct foreign keys
        # https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct-foreign-keys
        content_object=obj,
        permission=permission,
        **{
            user_or_group._meta.model_name: user_or_group
        }
    )

所有10条评论

+1

+1

+1

我通过从django.contrib.auth导入Group修复了这个错误,但是它现在似乎没有对数据库进行任何更改(请参阅#333)。 那是在 django 1.8 和 Guardian 1.3 上,所以如果有人可以尝试 1.7,那就太好了

我最终为迁移脚本使用了两个辅助函数:
https://gist.github.com/xuhcc/67871719116bdc0fee6c
(django-guardian==1.2.5)

不幸的是,仍然不喜欢 1.8/1.3。 使用你的辅助函数我得到了错误
ValueError: Cannot query "project": Must be "ContentType" instance

perm = Permission.objects.get(
            content_type=get_content_type(obj),
            codename=codename)

obj是一个名为 project 的模型实例,我是这样得到的:

projs = get_objects_for_user(user, 'api.view_project')
        for proj in projs:
                assign_perm(apps, 'api.edit_project', user, proj)

不幸的是,在迁移中使用assign_perms(或任何其他不在迁移本身中的依赖于模式的代码)是一个非常糟糕的主意。 我并不惊讶它也不起作用。

它不起作用的原因很可能在逻辑中找到权限模型不是使用迁移所需的apps.get_model()返回的正确模型。 这可能是可以修复的。

然而,这里有一个根本问题是无法解决的。 也就是说,数据库迁移不会尝试序列化assign_perm()函数或assign_perm()调用的任何函数。 因此,更高版本的 django-guardian 可以更改数据库架构并更新assign_perm()以使用新架构。 您的旧迁移将突然中断,因为它们现在正在使用旧数据库架构运行新的assign_perm()代码。

事实上,某些请求的功能(例如角色)可能需要架构中的这种更改。

这可能不是您要寻找的答案,但是我认为您必须使用较低级别的数据库操作来设置权限。 我的意思是直接与 Permission db 模型交互。 Django 迁移不应访问迁移之外的数据库模式相关函数。 这也包括 db 模型类上的自定义函数。

可能可以更好地记录此限制。 拉取请求表示赞赏。

因此关闭此错误。

你好
我对 1.4.4 版本 pf Guardian 和 django 1.9.7 有同样的问题
迁移中的任何assign_perm 都不起作用... :(
知道如何在迁移中完全固定或猴子修补吗?

它不工作的原因很可能在逻辑中找到权限模型不是使用迁移所需的 apps.get_model() 返回的正确模型。 这可能是可以修复的。

也许可以将身份验证组包裹起来,使其表现得像一个监护人组。

我在这里发布它,以防它对其他人有用,但我为初始设置迁移编写了这个相对通用的assign_perm方法,做了一些假设,但可能有帮助:

def assign_perm(perm, user_or_group, obj=None, apps=None):
    permission_model = apps.get_model('auth', 'Permission')
    permission = permission_model.objects.get(codename=perm)

    # Assumes object permission models live in the same app as the model they govern
    # and are named like `ProjectUserObjectPermission`/`ProjectGroupObjectPermission`
    obj_permission_model = apps.get_model(obj._meta.app_label, '{}{}ObjectPermission'.format(
        obj._meta.object_name,
        user_or_group._meta.object_name,
    ))
    obj_permission_model.objects.create(
        # `object_pk` and `content_type_id` keys if you're not using direct foreign keys
        # https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct-foreign-keys
        content_object=obj,
        permission=permission,
        **{
            user_or_group._meta.model_name: user_or_group
        }
    )
此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Dzejkob picture Dzejkob  ·  28评论

BenDevelopment picture BenDevelopment  ·  5评论

johnthagen picture johnthagen  ·  9评论

lukaszb picture lukaszb  ·  14评论

brianmay picture brianmay  ·  16评论