DRF:具有基于函数的视图的自定义权限类中的参数

lbr*_*ris 3 django django-rest-framework

我使用Django Rest Framework来构建我的 API,它工作得很好。我使用基于函数的视图来管理我的端点。它也工作得很好,但我试图添加自定义权限类并在其中添加参数不起作用。

我的端点之一的示例:

@api_view(http_method_names=["GET"])
@permission_classes([IsAuthenticated])
def team_kanban(request):
    """
    List all Helpdesk Teams with kanban fields.
    """
    teams = HelpdeskTeam.objects.all()
    return Response(HelpdeskTeamKanbanSerializer(teams, many=True).data)
Run Code Online (Sandbox Code Playgroud)

它工作没有任何问题。但是当我尝试这样做时:

@api_view(http_method_names=["GET"])
@permission_classes([IsAuthenticated, HasPermission("view_helpdeskteam")])
def team_kanban(request):
    """
    List all Helpdesk Teams with kanban fields.
    """
    teams = HelpdeskTeam.objects.all()
    return Response(HelpdeskTeamKanbanSerializer(teams, many=True).data)
Run Code Online (Sandbox Code Playgroud)

使用此自定义权限类:

from rest_framework import permissions


class HasPermission(permissions.BasePermission):
    """
    Allows access only to users who have the appropriate permission.
    """

    permission_codename = ""

    def __init__(self, permission_codename):
        super().__init__()
        self.permission_codename = permission_codename

    def has_permission(self, request, view):
        return request.user.has_permission(self.permission_codename)
Run Code Online (Sandbox Code Playgroud)

这不起作用。完整的错误是:

Traceback (most recent call last):
  File "C:\Program Files\Python37\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Program Files\Python37\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Program Files\Python37\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Program Files\Python37\lib\site-packages\django\views\generic\base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 497, in dispatch
    self.initial(request, *args, **kwargs)
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 415, in initial
    self.check_permissions(request)
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 331, in check_permissions
    for permission in self.get_permissions():
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 278, in get_permissions
    return [permission() for permission in self.permission_classes]    
  File "C:\Program Files\Python37\lib\site-packages\rest_framework\views.py", line 278, in <listcomp>
    return [permission() for permission in self.permission_classes]    
TypeError: 'HasPermission' object is not callable
Run Code Online (Sandbox Code Playgroud)

看来我的类无法使用参数调用。

我怎样才能做到这一点?

提前致谢 :)

Iai*_*ton 6

permission_classes必须传递权限类列表,而不是权限实例。动态创建权限类的一种方法是创建一个返回动态创建的类的方法,使用type

from rest_framework import permissions


class HasPermissionBase(permissions.BasePermission):
    """
    Allows access only to users who have the appropriate permission.
    """

    permission_codename = ""

    def has_permission(self, request, view):
        return request.user.has_permission(self.permission_codename)


def HasPermission(permission_codename):
    return type('HasPermission', (HasPermissionBase, ), {'permission_codename': permission_codename})
Run Code Online (Sandbox Code Playgroud)

或者您可以重写__call__自定义权限上的方法并返回,self以便在调用时它的行为就像一个类



class HasPermission(permissions.BasePermission):
    """
    Allows access only to users who have the appropriate permission.
    """

    permission_codename = ""

    def __init__(self, permission_codename):
        super().__init__()
        self.permission_codename = permission_codename

    def __call__(self):
        return self

    def has_permission(self, request, view):
        return request.user.has_permission(self.permission_codename)
Run Code Online (Sandbox Code Playgroud)