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

Django如何将动态URL参数传递到queryset实现数据过滤

解决方案

核心问题说明

你的代码存在4个典型错误:

  1. 缺失rest_framework.viewsets的导入声明,代码运行时会直接抛出未定义异常
  2. 类属性级别定义的queryset会在模块加载时就执行,此时无法获取请求时的动态URL参数,写死的过滤逻辑只会生效一次
  3. 错误重写ViewSet的__init__方法获取参数,DRF的所有路径参数都会默认存放在视图实例的self.kwargs字典中,不需要重写构造方法
  4. DRF的DefaultRouter.register方法不支持前缀中直接写路径参数,不能用路由器注册带动态参数的路径

可选修正方案

方案1:独立视图单独配置路由

第一步:修改views.py

from rest_framework import permissions, viewsets # 补全缺失的导入
from .serializers import ProductSerializer,CategorySerializer
from .models import Product,Category
from rest_framework.response import Response
from rest_framework.views import APIView

class ProductViewSet(viewsets.ModelViewSet):
    queryset=Product.objects.all()
    serializer_class= ProductSerializer

class CategoryViewSet(viewsets.ModelViewSet):
    queryset=Category.objects.all()
    serializer_class= CategorySerializer

class ProductbyCategory(viewsets.ModelViewSet):
    serializer_class= ProductSerializer
    # 重写get_queryset方法实现动态过滤,每次请求都会执行该方法
    def get_queryset(self):
        categoryid = self.kwargs.get('categoryid')
        return Product.objects.filter(categoryid=categoryid)

第二步:修改urls.py

from django.urls import path, include
from .views import ProductViewSet,CategoryViewSet,ProductbyCategory
from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'products', ProductViewSet)
router.register(r'category', CategoryViewSet)
# 删除原来的带参数的router.register语句,直接在urlpatterns中配置路径
urlpatterns = [
    path('',include(router.urls)),
    # 手动配置动态路径,绑定get请求到list方法
    path('sort-by-category/<int:categoryid>/', ProductbyCategory.as_view({'get': 'list'}), name='product-by-category'),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
] 

方案2:使用action装饰器(更符合DRF最佳实践,代码更简洁)

不需要单独写ProductbyCategory视图,直接在已有ProductViewSet上扩展接口:

第一步:修改views.py

from rest_framework import permissions, viewsets
from rest_framework.decorators import action # 导入action装饰器
from .serializers import ProductSerializer,CategorySerializer
from .models import Product,Category
from rest_framework.response import Response

class ProductViewSet(viewsets.ModelViewSet):
    queryset=Product.objects.all()
    serializer_class= ProductSerializer
    
    # 添加自定义动作,detail=False表示是列表级接口,url_path定义路径规则
    @action(detail=False, methods=['get'], url_path='sort-by-category/(?P<categoryid>\d+)')
    def filter_by_category(self, request, categoryid=None):
        filtered_products = self.get_queryset().filter(categoryid=categoryid)
        serializer = self.get_serializer(filtered_products, many=True)
        return Response(serializer.data)

class CategoryViewSet(viewsets.ModelViewSet):
    queryset=Category.objects.all()
    serializer_class= CategorySerializer

第二步:修改urls.py

不需要额外加配置,保持原来的路由器注册即可:

from django.urls import path, include
from .views import ProductViewSet,CategoryViewSet
from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'products', ProductViewSet)
router.register(r'category', CategoryViewSet)

urlpatterns = [
    path('',include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
] 

修改后访问路径为/products/sort-by-category/对应分类ID/即可获取对应分类的产品列表。


内容的提问来源于stack exchange,提问作者Phan Quang Thang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:36:01