Django REST Framework如何按category值过滤数据并配置独立URL
Django REST Framework 按分类映射独立URL实现方案
你现有代码基于ModelViewSet+DefaultRouter搭建,不需要重构现有逻辑,两种方案可快速实现category=2数据的独立URL访问:
方案1:自定义ViewSet Action(零额外路由配置,最适配现有代码)
直接在你已有的productviewset中新增一个GET方法的自定义Action,DefaultRouter会自动生成对应路由,不需要手动修改路由配置。
修改后的视图代码如下:
from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from .models import product from .serializers import productSerializer class productviewset(viewsets.ModelViewSet): queryset = product.objects.all() serializer_class = productSerializer pagination_class = None def create(self, request): serialized = productSerializer(data=request.data, many=True) if serialized.is_valid(): serialized.save() return Response(serialized.data, status=status.HTTP_201_CREATED) return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST) # 新增:返回category=2产品的接口 @action(detail=False, methods=["get"]) def category2(self, request): # 过滤分类为2的所有产品 category2_products = self.get_queryset().filter(category=2) serialized_data = self.get_serializer(category2_products, many=True) return Response(serialized_data.data) @action(detail=False, methods=["post"]) def delete(self, request): product.objects.all().delete() return Response("success")
配置完成后直接访问 GET /api/product/category2/ 即可拿到所有category=2的产品数据。
小提示:如果需要自定义URL路径,给
@action加url_path参数即可,比如要把路径改成category/type2,就写@action(detail=False, methods=["get"], url_path="category/type2"),最终访问地址会变成/api/product/category/type2/。
方案2:通用过滤+显式路由映射(适合多分类扩展场景)
如果后续需要支持任意分类值的过滤、以及更多独立分类URL,先接入过滤组件再做路由映射更灵活:
- 先给视图添加过滤能力,支持通过URL参数过滤分类:
from django_filters.rest_framework import DjangoFilterBackend class productviewset(viewsets.ModelViewSet): queryset = product.objects.all() serializer_class = productSerializer pagination_class = None # 新增过滤配置 filter_backends = [DjangoFilterBackend] filterset_fields = ["category"] # 原有create、delete方法保持不变
配置完成后本身就可以通过 GET /api/product/?category=2 拿到分类2的数据,如果你需要更语义化的独立URL(比如/api/category2-goods/),直接在urlpatterns里追加路由映射即可,不需要改视图:
router = routers.DefaultRouter() router.register(r'product', productviewset, basename='product') urlpatterns = [ path('api/', include(router.urls)), # 追加独立路由,直接绑定列表接口,预注入category=2的过滤参数 path( 'api/category2-goods/', productviewset.as_view({'get': 'list'}), {'category': 2}, name='category2-goods' ), ]
开发规范提示
- 现有代码里模型、序列化器、视图类都用了小写命名,不符合Python/Django的大驼峰类名规范,建议后续重构为
Product、ProductSerializer、ProductViewSet,避免出现命名空间冲突。 - 现有全量删除接口用POST请求且无权限校验,容易出现误操作,建议加上管理员权限限制。
内容的提问来源于stack exchange,提问作者das
相关产品推荐
相关产品推荐

