2020 年 3 月 30 日更新:我原来的解决方案只修补了对象权限,而不是请求权限。我在下面包含了一个更新,以使这项工作也与请求权限一起工作。
我知道这是一个老问题,但我最近遇到了同样的问题并想分享我的解决方案(因为接受的答案并不是我所需要的)。@GDorn 的回答让我走上了正轨,但它只适用于ViewSet
s 因为self.action
我已经解决了它创建自己的装饰器:
def method_permission_classes(classes):
def decorator(func):
def decorated_func(self, *args, **kwargs):
self.permission_classes = classes
# this call is needed for request permissions
self.check_permissions(self.request)
return func(self, *args, **kwargs)
return decorated_func
return decorator
permission_classes
我的装饰器没有像内置装饰器那样在函数上设置属性,而是包装调用并在被调用的视图实例上设置权限类。这样,法线get_permissions()
不需要任何更改,因为它只依赖于self.permission_classes
.
要使用请求权限,我们确实需要check_permission()
从装饰器调用,因为它是在属性被修补initial()
之前调用的。permission_classes
注意通过装饰器设置的权限是唯一调用对象权限的权限,但对于请求权限,它们是类范围权限的补充,因为在调用请求方法之前总是检查这些权限。如果您只想指定每个方法的所有权限,permission_classes = []
请在类上设置。
示例用例:
from rest_framework import views, permissions
class MyView(views.APIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,) # used for default APIView endpoints
queryset = MyModel.objects.all()
serializer_class = MySerializer
@method_permission_classes((permissions.IsOwnerOfObject,)) # in addition to IsAuthenticatedOrReadOnly
def delete(self, request, id):
instance = self.get_object() # ...
希望这可以帮助遇到同样问题的人!