You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:27:22