Django 1.11+DRF3.7.7过滤失效:无法筛选is_thumbnail=True的Video
嘿,我来帮你排查这个问题!你遇到的核心问题是get_queryset完全没被调用,导致过滤逻辑根本不生效,这通常和视图类的写法或者URL路由配置有关,咱们一步步来捋:
1. 先检查视图类的写法
这是最常见的问题点,首先要确保你的视图类没有同时定义queryset属性和get_queryset方法——DRF会优先使用硬编码的queryset,直接跳过get_queryset的调用。
错误示例(会跳过get_queryset)
from rest_framework import viewsets from .models import Video from .serializers import VideoSerializer class VideoViewSet(viewsets.ReadOnlyModelViewSet): queryset = Video.objects.all() # 这个属性会让DRF忽略get_queryset serializer_class = VideoSerializer def get_queryset(self): print("get_queryset被调用了!") return Video.objects.filter(is_thumbnail=True)
修正写法
要么直接删掉queryset属性,要么把它设为None,强制DRF调用get_queryset:
class VideoViewSet(viewsets.ReadOnlyModelViewSet): # 去掉queryset属性,或者设为queryset = None serializer_class = VideoSerializer def get_queryset(self): print("get_queryset被调用了!") return Video.objects.filter(is_thumbnail=True)
另外,如果你用的是APIView而非视图集,必须手动在get方法里调用get_queryset,否则它不会自动执行:
from rest_framework.views import APIView from rest_framework.response import Response from .models import Video from .serializers import VideoSerializer class VideoListAPIView(APIView): def get_queryset(self): print("get_queryset被调用了!") return Video.objects.filter(is_thumbnail=True) def get(self, request, *args, **kwargs): queryset = self.get_queryset() # 必须手动调用! serializer = VideoSerializer(queryset, many=True) return Response(serializer.data)
2. 检查URL路由配置
如果视图类写法没问题,那大概率是路由没正确指向你的视图,导致请求根本没走到这个视图类。
视图集的路由配置(推荐)
如果用的是ReadOnlyModelViewSet这类视图集,需要用DRF的路由注册器来生成路由:
# api/urls.py from rest_framework.routers import DefaultRouter from .views import VideoViewSet router = DefaultRouter() router.register(r'videos', VideoViewSet) # 自动生成list、detail等路由 urlpatterns = router.urls
然后在项目根路由里包含这个API路由:
# securedash_project/urls.py from django.conf.urls import url, include urlpatterns = [ # 其他项目路由 url(r'^api/', include('api.urls')), ]
普通ListAPIView的路由配置
如果用的是generics.ListAPIView,路由要直接指向视图的as_view()方法:
# api/urls.py from django.conf.urls import url from .views import VideoListAPIView urlpatterns = [ url(r'^videos/$', VideoListAPIView.as_view(), name='video-list'), ]
3. 快速验证视图是否被调用
可以临时在视图类里加个list方法的日志,确认请求是否真的走到了这个视图:
class VideoViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = VideoSerializer def list(self, request, *args, **kwargs): print("list方法被调用了!") return super().list(request, *args, **kwargs) def get_queryset(self): print("get_queryset被调用了!") return Video.objects.filter(is_thumbnail=True)
- 如果
list的日志也没输出:说明路由配置错误,请求没到达这个视图 - 如果
list日志输出但get_queryset没输出:回到第一步,检查是否有queryset属性冲突
4. 排除其他干扰
比如有没有使用第三方过滤插件、自定义的filter_backends,或者视图被其他Mixin/装饰器修改,导致get_queryset被覆盖?先把这些暂时注释掉,测试最基础的逻辑是否正常。
内容的提问来源于stack exchange,提问作者brewcrazy
相关产品推荐
相关产品推荐

