【问题标题】:Add prefetch_related() to Django Authentication backend将 prefetch_related() 添加到 Django 身份验证后端
【发布时间】:2020-05-05 18:32:05
【问题描述】:

在我的项目中,我同时拥有基于组和自定义用户的权限。

我有一个自定义身份验证后端,它主要检查用户是否具有组权限,然后查看他们是否有任何需要从检查的权限中删除的撤销权限。

现在我正在测试所述撤销权限的实现,我遇到了一个优化问题,因为我的 CustomUser 模型有一个 M2M 字段来保存这些与auth_permissions 相关的撤销权限,我的 BackendAuthentication 会检查它,我在页面加载时获得了疯狂的数据库点击量。

如何将预取的对象传递给我的 AuthBackend?

这是我的 AuthBackend:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import Permission

class UsersAuthenticationBackend(ModelBackend):
    def _get_revoked_perms(self, user_obj):
        if user_obj.is_superuser or user_obj.is_admin:
            revoked_perms = Permission.objects.none()
        elif hasattr(user_obj, 'revoked_permissions'):
            # this causes the issue, I need to pass in the prefetch related to my model backend...HOW?
            # this should be something like CustomUser.objects.prefetch_related('revoked_permissions')
            revoked_perms = getattr(user_obj, 'revoked_permissions').values_list('content_type__app_label', 'codename')
        else:
            revoked_perms = Permission.objects.none()

        revoked_perms = ["{}.{}".format(perm[0], perm[1]) for perm in revoked_perms]
        print(revoked_perms)
        return revoked_perms

    def has_perm(self, user_obj, perm, obj=None):
        if not user_obj.is_active:
            return False

        revoked_perms = self._get_revoked_perms(user_obj)
        all_perms = self.get_all_permissions(user_obj)
        allowed_perms = [p for p in all_perms if not p in revoked_perms]

        if isinstance(perm, str):
            return perm in allowed_perms
        elif isinstance(perm, Permission):
            return '{}.{}'.format(perm.content_type.app_label, perm.codename) in allowed_perms
        else:
            return False

这里是CustomUser的相关部分,如果你需要看的话

class CustomUser(AbstractUser, SafeDeleteModel):
    ...
    revoked_permissions = models.ManyToManyField(Permission, blank=True)

【问题讨论】:

    标签: django python-3.x django-authentication django-permissions


    【解决方案1】:

    我想出了一个解决方案来完成我所需要的,尽管它是一个不错的解决方法......

    我将“撤销权限”更改为“额外应用权限”(出于需求原因),并将模型字段从 M2M 关系更改为 JSONField(list),该字段将权限 content_type.app_labelcodename 存储为串联字符串,然后我将其用于比较。

    from django.contrib.auth.backends import ModelBackend
    from django.contrib.auth.models import Permission
    
    class UsersAuthenticationBackend(ModelBackend):
        def _get_allowed_perms(self, user_obj):
            if user_obj.is_superuser or user_obj.is_admin:
                allowed_perms = []
            elif hasattr(user_obj, 'extra_allowed_permissions'):
                allowed_perms = user_obj.extra_allowed_permissions
            else:
                allowed_perms = []
            # 'content_type__app_label'.'codename'
            allowed_perms = [perm for perm in allowed_perms]
            # print(allowed_perms)
            return allowed_perms
    
        def has_perm(self, user_obj, perm, obj=None):
            if not user_obj.is_active:
                return False
    
            allowed_perms = self._get_allowed_perms(user_obj)
            group_perms = self.get_group_permissions(user_obj)
            # concat the perms for comparison
            combined_perms = list(group_perms) + allowed_perms
    
            if isinstance(perm, str):
                return perm in combined_perms
            elif isinstance(perm, Permission):
                perm_string = '{}.{}'.format(perm.content_type.app_label, perm.codename)
                return perm_string in combined_perms
            else:
                return False
    
    

    这是模型更改:

    class CustomUser(AbstractUser, SafeDeleteModel):
        ...
        extra_allowed_permissions = JSONField(default=list, null=True, blank=True)
    
    

    【讨论】:

    • 请注意,由于 Django 中的优化问题很明显,这很好用并且实际上不是一个糟糕的选择,我只是认为使用 M2M 字段来保存权限会更好。但是,如果我因此不得不多打 155 次 DB 才能获得一个视图,那显然是不行的
    猜你喜欢
    • 1970-01-01
    • 2019-06-06
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 2021-10-20
    相关资源
    最近更新 更多