如何在Swagger中动态切换Django查询集的order_by字段
在Swagger中实现菜单列表的排序切换
针对你的需求(按菜单名称字母序或菜品数量降序排序),可以通过定义排序枚举参数+视图层处理排序逻辑+Swagger参数注解来实现,以下是具体步骤(基于Django REST Framework + drf-spectacular,当前主流的Swagger生成工具):
1. 预处理菜品数量统计
因为要按dishes的数量排序,需要先给Menu查询集添加菜品数字段:
from django.db.models import Count from rest_framework import generics from .models import Menu from .serializers import MenuSerializer
2. 定义合法排序选项的枚举类
用枚举类限定排序参数的有效值,避免用户输入无效内容,同时让Swagger自动生成下拉选择框:
from enum import Enum class MenuSortOption(str, Enum): NAME_ASC = "name" # 名称升序(字母序) DISHES_COUNT_DESC = "-dishes_count" # 菜品数量降序
3. 在视图层实现动态排序逻辑
在列表视图中接收排序参数,并重写get_queryset方法根据参数调整排序规则:
from drf_spectacular.utils import extend_schema, OpenApiParameter class MenuListView(generics.ListAPIView): serializer_class = MenuSerializer @extend_schema( parameters=[ OpenApiParameter( name="ordering", type=str, enum=[option.value for option in MenuSortOption], description="排序选项:name(名称升序)、-dishes_count(菜品数量降序)", required=False, default="name" ) ] ) def get_queryset(self): # 先给每个菜单标注菜品数量 queryset = Menu.objects.annotate(dishes_count=Count('dishes')) # 获取前端传入的排序参数,默认按名称升序 ordering = self.request.query_params.get("ordering", MenuSortOption.NAME_ASC.value) # 非法参数直接用默认值 if ordering not in [opt.value for opt in MenuSortOption]: ordering = MenuSortOption.NAME_ASC.value return queryset.order_by(ordering)
4. Swagger效果说明
配置完成后打开Swagger文档的菜单列表接口:
- 会看到
ordering参数的下拉选择框,选项就是你定义的两个排序规则 - 选择对应选项后发送请求,就能得到符合要求的排序结果
补充:若使用drf-yasg的配置方式
如果你用的是drf-yasg而非drf-spectacular,参数定义可替换为:
from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi class MenuListView(generics.ListAPIView): serializer_class = MenuSerializer @swagger_auto_schema( manual_parameters=[ openapi.Parameter( 'ordering', openapi.IN_QUERY, description="排序选项:name(名称升序)、-dishes_count(菜品数量降序)", type=openapi.TYPE_STRING, enum=[opt.value for opt in MenuSortOption], default=MenuSortOption.NAME_ASC.value ) ] ) def get_queryset(self): # 同上述视图逻辑 queryset = Menu.objects.annotate(dishes_count=Count('dishes')) ordering = self.request.query_params.get("ordering", MenuSortOption.NAME_ASC.value) if ordering not in [opt.value for opt in MenuSortOption]: ordering = MenuSortOption.NAME_ASC.value return queryset.order_by(ordering)
核心逻辑是:用枚举类约束参数范围让Swagger生成可视化选择控件,在视图层结合annotate统计关联字段数量,再根据参数动态调整查询集排序规则。
内容的提问来源于stack exchange,提问作者chlebastian
相关产品推荐
相关产品推荐

