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

使用Django Rest Framework ViewSet遇404错误,需URL参数过滤查询集

解决DRF ViewSet中URL参数过滤查询集的404问题

嘿,刚上手DRF遇到这种问题太正常了,咱们一步步拆解排查,搞定它~

首先,先明确几个核心点:404错误要么是路由不匹配,要么是请求的资源确实不存在(但用URL参数过滤列表的话,正常应该返回空数组而非404,所以大概率是路由或过滤逻辑的问题)。

第一步:补全正确的路由配置

你提到用了DefaultRouter,先确保你的urls.py是这么写的(别漏了关键的注册和include步骤):

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import OffreViewSet  # 替换成你实际的ViewSet路径

router = DefaultRouter()
# 注册Offre的ViewSet,路由前缀设为offres
router.register(r'offres', OffreViewSet)

urlpatterns = [
    # 把router生成的路由包含进来
    path('', include(router.urls)),
]

这一步错了的话,哪怕过滤逻辑对了,访问的路径不对直接就404了。

第二步:在ViewSet中实现URL参数过滤

要通过URL查询参数(比如?secteur=IT)过滤查询集,最直观的方式是重写get_queryset方法,手动处理参数。先看完整的ViewSet代码:

from rest_framework import viewsets
from .models import Offre
from .serializers import OffreSerializer  # 别忘了写对应的序列化器!

class OffreViewSet(viewsets.ModelViewSet):
    # 基础查询集
    queryset = Offre.objects.all()
    serializer_class = OffreSerializer

    def get_queryset(self):
        # 先拿到父类的基础查询集
        queryset = super().get_queryset()
        
        # 从URL查询参数中获取secteur值
        secteur_param = self.request.query_params.get('secteur', None)
        if secteur_param:
            # 过滤出secteur匹配的记录
            queryset = queryset.filter(secteur=secteur_param)
        
        # 如果你还想支持按招聘者ID过滤,同样的逻辑
        recruteur_id = self.request.query_params.get('idRecruteur', None)
        if recruteur_id:
            # 外键过滤用_id后缀更高效,也可以用idRecruteur=Recruteur.objects.get(id=recruteur_id)
            queryset = queryset.filter(idRecruteur_id=recruteur_id)
        
        return queryset

为什么会出现404?常见坑点

  1. 请求路径写错了:
    正确的过滤请求应该是GET /offres/?secteur=IT(参数在?后面),如果你写成/offres/secteur=IT/或者/offres/IT/,路由会认为你在访问某个详情资源(比如主键为IT的Offre),自然返回404。
  2. 参数名拼写错误:
    比如你在URL里传的是sector=IT,但代码里写的是secteur,过滤后查询集为空,但列表视图会返回空数组,不会404——除非你误访问了详情端点(比如/offres/123/但123不存在)。
  3. ViewSet关联错误:
    如果serializer_class没定义或者写错,可能导致序列化错误,但一般是500而非404;如果queryset没设置,DRF也会报错,但也不是404。

进阶:用django-filter简化过滤

如果需要更复杂的过滤逻辑(比如模糊匹配、范围过滤),推荐用django-filter库,配置更省心:

  1. 先安装:pip install django-filter
  2. 在settings.py中添加配置:
INSTALLED_APPS = [
    ...
    'django_filters',
]

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
  1. 修改ViewSet,直接指定可过滤字段:
class OffreViewSet(viewsets.ModelViewSet):
    queryset = Offre.objects.all()
    serializer_class = OffreSerializer
    # 指定允许过滤的字段,直接用?secteur=IT&idRecruteur=1即可过滤
    filter_fields = ['secteur', 'idRecruteur']

最后排查步骤

  1. 确认请求URL是http://localhost:8000/offres/?secteur=你的行业(替换成你数据库中存在的secteur值)
  2. 检查get_queryset里的参数名和URL中的参数名完全一致
  3. 打开DRF的API界面(比如/offres/),直接在界面上输入参数测试,避免手动拼URL出错

内容的提问来源于stack exchange,提问作者M1rwen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:26:16