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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 22:27:21