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
相关产品推荐
相关产品推荐

