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

如何在Django父类BaseView中使用drf-yasg生成Swagger文档?

解决drf-yasg父类装饰器无法识别子类属性的方案

下面提供几种无需逐个配置子类HTTP方法及装饰器的解决方案,核心思路是延迟获取子类属性,让swagger在生成文档时动态读取子类的serializer_class、model等配置:

方案1:利用Lambda延迟序列化器获取

直接在父类的@swagger_auto_schema中用lambda函数动态调用视图实例的序列化器方法,替代硬编码的序列化器类:

from drf_yasg.utils import swagger_auto_schema
from rest_framework.generics import GenericAPIView

class BaseView(GenericAPIView):
    # 确保子类重写此属性
    serializer_class = None
    model = None

    @swagger_auto_schema(
        # POST/PUT请求动态获取请求体序列化器
        request_body=lambda self: self.get_serializer_class(),
        # 响应动态获取序列化器
        responses={200: lambda self: self.get_serializer_class()},
        # 动态生成接口描述(可选)
        operation_description=lambda self: f"创建{self.model._meta.verbose_name}数据"
    )
    def post(self, request, *args, **kwargs):
        # 通用POST逻辑
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    @swagger_auto_schema(
        responses={200: lambda self: self.get_serializer_class(many=True)},
        operation_description=lambda self: f"获取{self.model._meta.verbose_name_plural}列表"
    )
    def get(self, request, *args, **kwargs):
        # 通用GET列表逻辑
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

# 子类仅需重写核心属性
class UserView(BaseView):
    serializer_class = UserSerializer
    model = User
    queryset = User.objects.all()

lambda函数会在swagger生成文档时执行,此时已经绑定了子类的实例,能正确拿到子类的序列化器和模型信息。

方案2:自定义类装饰器批量处理HTTP方法

如果父类包含多个HTTP方法(GET/POST/PUT/DELETE),可以写一个类装饰器,自动为所有方法注入动态swagger配置:

from drf_yasg.utils import swagger_auto_schema
from rest_framework.generics import GenericAPIView

def auto_swagger_base(cls):
    # 遍历需要处理的HTTP方法
    for method_name in ['get', 'post', 'put', 'delete']:
        if not hasattr(cls, method_name):
            continue
            
        original_method = getattr(cls, method_name)
        # 根据请求方法动态配置swagger参数
        swagger_kwargs = {}
        if method_name in ['post', 'put']:
            swagger_kwargs['request_body'] = lambda self: self.get_serializer_class()
        
        # 统一配置响应序列化器
        swagger_kwargs['responses'] = {
            200: lambda self: self.get_serializer_class(many=True if method_name == 'get' else False)
        }
        
        # 为原方法添加swagger装饰
        decorated_method = swagger_auto_schema(**swagger_kwargs)(original_method)
        setattr(cls, method_name, decorated_method)
    
    return cls

# 父类应用装饰器
@auto_swagger_base
class BaseView(GenericAPIView):
    serializer_class = None
    model = None

    def get(self, request, *args, **kwargs):
        # 通用GET逻辑
        pass

    def post(self, request, *args, **kwargs):
        # 通用POST逻辑
        pass

# 子类正常继承配置
class BookView(BaseView):
    serializer_class = BookSerializer
    model = Book
    queryset = Book.objects.all()

这个装饰器会自动遍历父类的HTTP方法,为每个方法添加带动态参数的swagger装饰,子类无需做额外配置。

方案3:重写swagger_auto_schema装饰器

自定义一个全局的swagger装饰器,默认自动读取当前视图的serializer_class,简化父类代码:

from drf_yasg.utils import swagger_auto_schema as original_swagger

def swagger_auto_schema(**kwargs):
    # 自动注入动态请求体和响应配置
    if 'request_body' not in kwargs:
        kwargs['request_body'] = lambda self: self.get_serializer_class()
    if 'responses' not in kwargs:
        kwargs['responses'] = {200: lambda self: self.get_serializer_class()}
    
    return original_swagger(**kwargs)

# 父类使用自定义装饰器
class BaseView(GenericAPIView):
    serializer_class = None
    model = None

    @swagger_auto_schema(operation_description="创建资源")
    def post(self, request, *args, **kwargs):
        pass

    @swagger_auto_schema(operation_description="获取资源列表")
    def get(self, request, *args, **kwargs):
        pass

# 子类配置属性即可
class OrderView(BaseView):
    serializer_class = OrderSerializer
    model = Order
    queryset = Order.objects.all()

这种方式下,父类的装饰器会自动处理序列化器的动态获取,子类只需要专注于业务属性的配置。


内容的提问来源于stack exchange,提问作者joseph Kalash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:55:24