如何为@extend_schema动态设置响应(基于Mixin子类Serializer)
问题:为drf_spectacular的@extend_schema动态设置响应(Mixin被多子类继承)
我希望为drf_spectacular的@extend_schema动态设置响应。该Mixin被多个子类继承,不同子类的响应会因各自的Serializer而不同,因此想要动态配置响应,是否可行?
代码示例:
class Mixin: @extend_schema( request=None, responses={ status.HTTP_200_OK: self.__class__.get_serializer(), # <--- self无法直接使用 status.HTTP_204_NO_CONTENT: None, } ) @action(detail=True, methods=['post'], url_path='decline') def decline(self, request, **kwargs): # 业务逻辑处理
我尝试过修补viewset并编写动态选择Serializer的函数,但发现响应处于静态上下文,想确认是否真的能实现动态设置?
可行,以下是两种实用实现方式:
方式一:使用extend_schema_view在类层面配置
drf_spectacular提供的extend_schema_view装饰器支持在类级别动态覆盖视图动作的Schema配置。你可以让Mixin仅定义基础的action方法,然后在每个子类中通过extend_schema_view指定该子类对应的响应Serializer:
from drf_spectacular.utils import extend_schema, extend_schema_view from rest_framework import viewsets, status class BaseDeclineMixin: @action(detail=True, methods=['post'], url_path='decline') def decline(self, request, **kwargs): # 通用业务逻辑处理 # 子类1:配置专属的响应Serializer @extend_schema_view( decline=extend_schema( request=None, responses={ status.HTTP_200_OK: Subclass1Serializer, status.HTTP_204_NO_CONTENT: None, } ) ) class Subclass1ViewSet(BaseDeclineMixin, viewsets.ModelViewSet): serializer_class = Subclass1Serializer # 子类2:配置另一个响应Serializer @extend_schema_view( decline=extend_schema( request=None, responses={ status.HTTP_200_OK: Subclass2Serializer, status.HTTP_204_NO_CONTENT: None, } ) ) class Subclass2ViewSet(BaseDeclineMixin, viewsets.ModelViewSet): serializer_class = Subclass2Serializer
方式二:利用响应字段的可调用特性自动适配子类
drf_spectacular允许responses中的值为可调用对象,该对象会在生成Schema时接收当前视图实例作为参数。基于此,你可以编写一个动态获取Serializer的函数,让Mixin自动适配子类的serializer_class:
from drf_spectacular.utils import extend_schema from rest_framework import status def get_view_serializer(view): # 直接通过视图实例获取子类定义的Serializer return view.get_serializer() class DeclineMixin: @extend_schema( request=None, responses={ status.HTTP_200_OK: get_view_serializer, status.HTTP_204_NO_CONTENT: None, } ) @action(detail=True, methods=['post'], url_path='decline') def decline(self, request, **kwargs): # 通用业务逻辑处理
这种方式下,无论Mixin被哪个子类继承,生成Schema时都会自动调用子类的get_serializer()方法,获取对应的序列化器作为响应Schema。
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

