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

drf_spectacular自定义路由Schema显示异常求助

解决drf_spectacular自定义路由Schema异常问题

问题场景

使用drf_spectacular生成接口文档时,自定义的unique_cities路由错误沿用了CRUD接口的SportsPerson序列化器Schema:

  • 接口实际返回城市列表结构
  • Swagger中却显示完整的SportsPerson模型字段结构
  • 尝试过@extend_schema配置但未生效

相关代码

自定义路由代码:

@action(detail=False, methods=['GET'])
def unique_cities(self, request):
    """Getting unique cities from DB sports_person."""
    unique_cities = SportsPerson.objects.values_list('city', flat=True)
    return Response({'unique_cities': list(unique_cities)})

接口实际返回:

{
    "unique_cities": [
        "New-York",  
        "Kyiv",
        "Test"
    ]
}

Swagger错误显示的Schema:

{
    "id": 0,
    "first_name": "string",
    "last_name": "string",
    "birth_day": "2023-09-13",
    "rank": "string",
    "city": "string",
    "team": "string"
}

可行解决方案

方案1:使用OpenApi工具类明确响应结构

直接通过OpenApiResponse和OpenApiTypes指定响应类型,避免框架自动继承默认序列化器:

from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiTypes

@extend_schema(
    responses={
        200: OpenApiResponse(
            response=OpenApiTypes.OBJECT,
            description='返回所有唯一城市列表',
            examples=[
                {
                    "unique_cities": ["New-York", "Kyiv", "Test"]
                }
            ]
        )
    }
)
@action(detail=False, methods=['GET'])
def unique_cities(self, request):
    """Getting unique cities from DB sports_person."""
    unique_cities = SportsPerson.objects.values_list('city', flat=True).distinct()
    return Response({'unique_cities': list(unique_cities)})

方案2:创建自定义序列化器(推荐)

为该接口单独定义序列化器,适配DRF和drf_spectacular的Schema生成逻辑:

from rest_framework import serializers
from drf_spectacular.utils import extend_schema

class UniqueCitiesSerializer(serializers.Serializer):
    unique_cities = serializers.ListField(child=serializers.CharField())

@extend_schema(
    responses={200: UniqueCitiesSerializer},
    examples={
        "application/json": {
            "unique_cities": ["New-York", "Kyiv", "Test"]
        }
    }
)
@action(detail=False, methods=['GET'])
def unique_cities(self, request):
    """Getting unique cities from DB sports_person."""
    unique_cities = SportsPerson.objects.values_list('city', flat=True).distinct()
    return Response({'unique_cities': list(unique_cities)})

方案3:强制覆盖默认Schema生成逻辑

使用OpenAPI原始Schema结构定义响应,并设置override=True强制覆盖默认规则:

from drf_spectacular.utils import extend_schema

@extend_schema(
    responses={
        200: {
            'type': 'object',
            'properties': {
                'unique_cities': {
                    'type': 'array',
                    'items': {'type': 'string'}
                }
            }
        }
    },
    examples={
        "application/json": {
            "unique_cities": ["New-York", "Kyiv", "Test"]
        }
    },
    override=True
)
@action(detail=False, methods=['GET'])
def unique_cities(self, request):
    """Getting unique cities from DB sports_person."""
    unique_cities = SportsPerson.objects.values_list('city', flat=True).distinct()
    return Response({'unique_cities': list(unique_cities)})

注意事项

  • 确保drf_spectacular版本为最新,旧版本可能存在@extend_schema兼容性问题
  • 建议在values_list后添加.distinct(),与接口描述的"unique cities"逻辑一致
  • 若使用方案2,自定义序列化器可复用在其他需要返回相同结构的接口中

内容的提问来源于stack exchange,提问作者Viktor Paradiuk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:53:29