Django-filters 无法与 Viewset 协同工作

9

我一直在尝试使用django-filters,但对象没有被过滤。此外,权限在部分更新视图中也无法正常工作。

我有一个Viewset,其中包含基本操作,例如- list(),retrieve(),destroy(),partial_update()以及其他一些操作,并尝试对其应用过滤器。

经过一些研究,我发现由于我通过过滤器创建了查询集,因此我将不得不覆盖get_queryset()方法。然而,那似乎也没有起作用。过滤器只能与ModelViewSetListApiView配合使用吗?

ViewSet -

class PostViewSet(viewsets.ViewSet):
"""
The Endpoint to list, retrieve, create and delete Posts.

"""
filter_backends = (DjangoFilterBackend, )
# filterset_class = PostFilter
filter_fields = ('pet_age', 'pet_gender', 'breed')

def get_permissions(self):

    if self.action == 'partial_update' or self.action == 'update':
        permission_classes = [IsPostAuthor, ]

    elif self.action == 'create' or self.action == 'destroy':
        permission_classes = [IsAuthenticated, ]

    else:
        permission_classes = [AllowAny, ]

    return[permission() for permission in permission_classes]

def get_queryset(self):
    return Post.objects.active() # This is implemented via custom Manager

def list(self, request, *args, **kwargs):
    """
    Method for Post listing. It can be accessed by anyone.
    """

    serializer = PostListSerializer(self.get_queryset(), many=True, context={"request": request})

    return Response(serializer.data)
# REST CODE TRUNCATED

权限 -

class IsPostAuthor(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
"""

def has_object_permission(self, request, view, obj):
    if request.user.is_authenticated:
        if view.action in ['partial_update', 'update']:
            return obj.user.id == request.user.id
        return False

    return False

后置过滤器 -

class PostFilter(filters.FilterSet):

class Meta:
    model = Post
    fields = ('pet_age', 'pet_gender', 'breed', )

经理 -

class PostManager(models.Manager):

def active(self):
    return self.filter(post_status='Active')

非常感谢您的帮助。


“权限不起作用”是什么意思?看起来您没有将“IsPostAuthor”添加到视图中。 - JPG
我正在基于视图操作检查权限,即我想将 partial_update() 方法限制为只能由创建帖子(作者)的用户访问。为此,我重写了 _get_permissions()_,如 docs 中所述。 - 5parkp1ug
2个回答

14

好的,终于在 DRF文档 中找到了解决方案。问题在于,在普通的ViewSet情况下,您需要重写 filter_queryset() 方法,并相应地返回适当的 查询集。 然后按照 Aman 的建议使用 filter_queryset 下的 查询集 -

serializer = PostListSerializer(self.filter_queryset(self.get_queryset()), many=True, context={"request": request})

以下是代码,供仍然遇到问题的人参考 -

filter_queryset -

def filter_queryset(self, queryset):
    filter_backends = (DjangoFilterBackend, )

    # Other condition for different filter backend goes here

    for backend in list(filter_backends):
        queryset = backend().filter_queryset(self.request, queryset, view=self)
    return queryset

2
你能分享一个覆盖查询集的完整视图集吗? - Harry Moreno

3

您已经覆盖了列表方法,因此调用filter_queryet方法将无法工作。

def list(self, request, *args, **kwargs):
    """
     Method for Post listing. It can be accessed by anyone.
     """

    serializer = PostListSerializer(self.filter_queryset(self.get_queryset()), many=True, context= . 
     {"request": request})

    return Response(serializer.data)

谢谢您的回复。然而,方法_filter_queryset()_是在_PostFilter_下实现的,因此我们无法将其引用为_self.filter_queryset()_。另外,我尝试重写此方法,但也没有起作用。我在想这是否与ViewSet有关。我应该通过_ModelViewSet_实现视图吗? - 5parkp1ug
请查看 https://github.com/encode/django-rest-framework/blob/master/rest_framework/mixins.py 中的 ListModelMixin,它调用了 self.filter_queryset(self.get_queryset())。 - aman kumar
是的,但我没有使用mixin。无论如何,问题现在已经解决了。不过还是感谢您的建议。 - 5parkp1ug
viewsets.ViewSet 是一个使用了 mixin 的类。 - aman kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接