能否在DRF中通过不同URL模式过滤ListView?用ViewSets实现分类、子分类路由
当然没问题!完全可以只靠Django REST Framework的ViewSets和Routers实现你要的分类、子分类商品列表路由,我给你详细说说具体怎么操作:
核心思路
DRF的默认Router只会生成标准的CRUD路由(比如/items/、/items/<pk>/),但我们可以通过给ViewSet添加自定义Action,再让Router自动识别并生成你需要的/items/category/、/items/category/subcategory/这类嵌套路由。
具体实现代码
1. 改造你的ItemViewSet
在原本的ItemViewSet里添加两个自定义Action方法,分别处理分类和子分类的商品列表查询:
from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.response import Response from .models import Item from .serializers import ItemSerializer class ItemViewSet(viewsets.ModelViewSet): queryset = Item.objects.all() serializer_class = ItemSerializer # 展示指定分类下的商品列表 @action(detail=False, methods=['get'], url_path='category/(?P<category_slug>[^/.]+)') def list_by_category(self, request, category_slug=None): # 这里假设你的Category模型用slug作为标识,要是用id就改成category__id=category_slug filtered_items = self.queryset.filter(category__slug=category_slug) serializer = self.get_serializer(filtered_items, many=True) return Response(serializer.data) # 展示指定子分类下的商品列表 @action(detail=False, methods=['get'], url_path='category/(?P<category_slug>[^/.]+)/subcategory/(?P<subcategory_slug>[^/.]+)') def list_by_subcategory(self, request, category_slug=None, subcategory_slug=None): # 同样,子分类如果用id就替换成subcategory__id=subcategory_slug filtered_items = self.queryset.filter( category__slug=category_slug, subcategory__slug=subcategory_slug ) serializer = self.get_serializer(filtered_items, many=True) return Response(serializer.data)
2. 保持Router配置不变
你的Router注册代码不需要修改,还是像之前一样注册ItemViewSet:
from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import ItemViewSet router = DefaultRouter() router.register(r'items', ItemViewSet) urlpatterns = [ path('', include(router.urls)), ]
关键细节说明
@action装饰器的detail=False:表示这是列表级别的Action,不会生成带<pk>的路由,符合你要的列表展示需求。url_path参数:用正则表达式捕获分类/子分类的标识(这里用slug,你可以换成id,只需要修改正则和过滤条件),Router会自动把这个路径拼接到/items/后面,生成你要的路由:/items/category/<你的分类slug>//items/category/<你的分类slug>/subcategory/<你的子分类slug>/
- 扩展性:如果需要给这些接口加权限、分页、过滤,直接在ViewSet里配置(比如加
permission_classes、pagination_class),和普通的ViewSet配置完全一致。
额外提示
如果你的分类/子分类用的是数据库ID而不是slug,只需要做两处修改:
- 把
url_path里的正则改成(?P<category_id>\d+)和(?P<subcategory_id>\d+) - 把过滤条件里的
category__slug改成category__id,subcategory__slug改成subcategory__id
内容的提问来源于stack exchange,提问作者MiniGunnR
相关产品推荐
相关产品推荐

