【问题标题】:Django REST Framework: Object level permissions not working according to tutorialDjango REST Framework:对象级权限不按照教程工作
【发布时间】:2016-09-20 18:13:22
【问题描述】:

我有一个包含用户和任务的基本应用程序,我希望 TaskDetails 只能由所有者访问。视图、权限和设置如下:

views.py:

from cardinal.permissions import IsOwner

class TaskDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    permissions_classes = (permissions.IsAuthenticatedOrReadOnly,
                           IsOwner)

permissions.py:

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        print("Hit IsOWnerOrReadOnly")
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.owner == request.user


class IsOwner(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        print("Hit IsOwner")
        return obj.owner == request.user


class IsUser(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        print("Hit IsUser")
        return obj.username == request.user.username

settings.py:

REST_FRAMEWORK = {
    # 'DEFAULT_PERMISSION_CLASSES': (
    #     'rest_framework.permissions.IsAuthenticated',
    #     'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    #     'cardinal.permissions.IsOwnerOrReadOnly',
    #     'cardinal.permissions.IsOwner',
    # ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

当我以“Bob”身份登录时,我可以访问“Susi”的任务并且权限不会触发。当我在设置中取消注释默认权限时,一切正常,但我不想将我写的每个权限都设置为“默认”以使其正常工作。

我查看了其他一些答案,其中一个建议在 TaskDetail 视图中覆盖 get_object 方法:

def get_object(self):
    obj = get_object_or_404(self.get_queryset())
    self.check_object_permissions(self.request, obj)
    return obj

当我尝试这样做时,我得到了错误:

get() returned more than one Task -- it returned 7!

如何在不设置默认设置的情况下正确使用对象级权限?

更新

不知道如何或为什么,但我通过导入整个应用程序并指定完整路径让它工作。

import cardinal

class TaskDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    permission_classes = (cardinal.permissions.IsOwner,)

【问题讨论】:

    标签: django api python-3.x permissions django-rest-framework


    【解决方案1】:

    您的代码中有两个问题:

    首先,错误是因为您将一个包含多个对象 (Task.objects.all()) 的查询集传递给 get_object_or_404 而没有指定一个特定的 pk。 See the third example of this section 在文档中。

    其次,如果权限检查未返回 true,则需要引发错误。现在您检查权限,但它是否返回TrueFalse 对代码没有影响。

    一种解决方案是执行以下操作,假设您的 DetailView 的 URLConf 具有 pk kwarg(如果不同,请替换您覆盖的 kwarg):

    def get_object(self):
        obj = get_object_or_404(self.get_queryset(), pk=self.kwargs.get('pk'))
        if self.check_object_permissions(self.request, obj):
            return obj
        else:
            raise Http404()
    

    【讨论】:

    • 我尝试了该代码 sn-p,现在每当我转到 TaskDetail 时,它都会返回“detail”:“未找到。我放入了一些打印语句,它遇到了 else 子句,但是它永远不会达到任何任务的“IsOwner”权限。有什么想法吗?
    • @KyleTruong 听起来get_object_or_404 正在返回 404,这是未找到对象时该函数的默认响应。
    • 据我所知,self.check_object_permissions(self.request, obj) 方法没有返回任何内容。因此,必须简单地调用它。如有必要,它将引发异常。否则,请继续。
    猜你喜欢
    • 1970-01-01
    • 2017-05-04
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多