【问题标题】:Django REST Framework: apply filter to list view but not detail viewDjango REST Framework:将过滤器应用于列表视图而不是详细视图
【发布时间】:2016-04-25 15:35:32
【问题描述】:

在使用ModelViewSet 时,使用 Django REST 框架是否可以仅过滤列表结果而不过滤详细结果?

我有一个拥有所有者的对象列表,我只希望用户在访问对象列表时看到他们拥有的对象。为此,我实现了一个基于rest_framework.filters.BaseFilterBackend 的新过滤器后端,它适用于列表。

当我尝试访问不属于我的用户的对象时出现问题:我得到“404 未找到”而不是“403 禁止”。

换句话说,过滤似乎不仅适用于列表,还适用于详细视图。有没有办法改变这一点,以便在访问我无权查看的对象时得到预期的 403?

我已经有一个权限类,它可以防止用户看到他不拥有的对象,但它甚至不会被调用,除非我注释掉视图集类上的 filter_backends 属性。

另一种思考方式是,我只想列出用户有权查看的对象。

【问题讨论】:

    标签: python django rest django-rest-framework


    【解决方案1】:

    您要引发的 rest_framework 异常是 PermissionDenied 以返回 403,因此请不要使用 get_object_or_404

    应用您想要的逻辑,并在用户不应该位于该 DetailView 端点时引发异常。

    from rest_framework.exceptions import PermissionDenied
    
    class UserViewSet(viewsets.ViewSet):
    
        model = User
    
        def retrieve(self, request, pk=None):
            try:
                return self.model.objects.filter(foo='bar').get(pk=pk)
            except User.DoestNotExist:
                # can't find the User based upon the filter foo='bar'
                # that represents a object permissions filter
                raise PermissionDenied("message to accompany the 403 error if desired")
    

    【讨论】:

    • self.model 似乎不是ModelViewSet 类的有效属性,我不得不使用模型类本身(编辑您的答案以反映这一点)。此外,这将需要我为我想要进行此更改的所有类覆盖retrieve 方法,这非常麻烦,因为我有很多。更重要的是,即使对于不存在的对象,这似乎也会引发 403,而不是应该的 404。这与我试图避免的情况完全相反。我希望有更好的方法来做到这一点。
    【解决方案2】:

    您可以检查pk 是否在视图 kwargs 中

    class MyFilterBackend(BaseFilterBackend):
        def filter_queryset(self, request, queryset, view):
            if 'pk' not in view.kwargs:
                queryset = queryset.filter(...)
            return queryset
    

    【讨论】:

      猜你喜欢
      • 2018-10-09
      • 2020-12-18
      • 2020-05-27
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多