【问题标题】:How to check object level permission efficiently in DRF?如何在 DRF 中有效地检查对象级权限?
【发布时间】:2021-06-07 04:56:24
【问题描述】:

场景:在 DRF 中,我必须编写以下代码行为用户检查权限

class RetrieveCampaignListView(APIView) :

authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]


def get(self, request , *args, **kwargs):

    if request.user.has_perm('campaign.view_campaign'):

        try:
            #some view code
        
        except:

            return Response({"status":False}, status=status.HTTP_404_NOT_FOUND)
    else:
        return Response({"status":"Sorry User is not permitted"})

但我想缩短

request.user.has_perm('campaign.view_camapign') and it's else condition

变成这样。

@check_permission('campaign.view_campaign') 

任何帮助都将受到高度重视。

【问题讨论】:

标签: python django django-models django-rest-framework django-views


【解决方案1】:

您可以使用 DRF 自定义权限:

from rest_framework import permissions


class ViewCampaignPermission(permissions.BasePermission):
    message = 'Sorry User is not permitted'

    def has_permission(self, request, view):
        return request.user.has_perm('campaign.view_campaign'):

class RetrieveCampaignListView(APIView) :
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated, ViewCampaignPermission]
    ...

见:https://www.django-rest-framework.org/api-guide/permissions/#custom-permissions

或者如果你真的想要一个装饰器,你可以使用类似的东西:

from functools import wraps
from rest_framework.views import APIView

def has_permission(permission):
    def has_permission_decorator(func):
        @wraps(func)
        def has_permission_wrapper(*args, **kwargs):
            request = args[0].request
            if not request.user.has_perm(permission):
                return Response(status='Sorry User is not permitted'})
            return func(*args, **kwargs)
        return has_permission_wrapper
    return has_permission_decorator


class RetrieveCampaignListView(APIView):
    @has_permission('campaign.view_campaign')
    def get(self, request, *args, **kwargs):
        pass

但这仅适用于一个权限字符串。

【讨论】:

  • 感谢您的建议,但如果我想实现另一个权限,比如campaign.add_campaign 怎么办?我应该创建另一个自定义权限,可能是我试图避免的 AddCampaignPermission。我想做一个普通的装饰器或函数或类,其输入参数是权限代码名。
  • 我想实现 @check_permission("permission_codename") 之类的东西,而不是为每个 code_name 创建整个自定义权限。很想听听对此@bdbd 的反馈
  • 已编辑。看看装饰器是否有意义。但我建议不要使用装饰器方法,因为这只适用于一个权限。
  • 装饰器方法有助于实现多权限,因为 code_name 将是传递给它的参数。
  • @bdbd 为什么不维护一个你想要检查的权限列表,你可以反复检查哪些权限是满足的。
猜你喜欢
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多