在django和DRF中引入Swagger/OpenAPI 2.0风格的接口文档

0
(0)

DRF即djangorestframework,是django框架上非常强大的插件,通过增强对视图的控制,提供强大的API管理功能。因项目中很多成员习惯了Swagger/OpenAPI 2.0风格的文档。 DRF的API文档功能略显简单,于是找到了drf-yasg组件,简单的配置后可以完美的输出swagger风格的文档。根据官方文档介绍,如果需要OpenAPI3.0风格的文档,需要需要 drf-spectacular组件

第一步,安装

pip install drf-yasg

第二步,配置

安装组件后,在settings.py中,注册组件, 需要把drf_yasg放到 django.contrib.staticfiles后面,用于管理css/js文件

INSTALLED_APPS = [
   ...
   'django.contrib.staticfiles',  # required for serving swagger ui's css/js files
   'drf_yasg',
   ...
]

第三步,在settings.py同目录下,创建schema_config.py文件,管理swagger配置

# 如果需要支持https,需要定义此类
class BothHttpAndHttpsSchemaGenerator(OpenAPISchemaGenerator):
    def get_schema(self, request=None, public=False):
        schema = super().get_schema(request, public)
        schema.schemes = ['http', 'https']
        return schema

schema_view = get_schema_view(
   openapi.Info(
      title="我的系统 OpenAPI文档",
      default_version='v1',
      description="api desc",
      terms_of_service="https://www.google.com/policies/terms/",
      contact=openapi.Contact(email="contact@snippets.local"),
      license=openapi.License(name="My License"),
   ),
   generator_class=BothHttpAndHttpsSchemaGenerator,  # 用于支持https,如果不需要https,本行可以注释
   public=True,
   permission_classes=[permissions.IsAuthenticated],  # IsAuthenticated代表需要登录后可访问,还可以配置成 AllowAny,无需验证即可访问
)

第四步,在主路由urls.py的urlpatterns中注册该配置

from schema_config import schema_view
urlpatterns = [
   path('swagger.<format>/', schema_view.without_ui(cache_timeout=0), name='schema-json'),  # json格式输出
   path('swagger-ui.html', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),  # swagger风格文档
   path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),  # redoc风格文档
   ...
]

第五步,配置完成后启动项目,访问相应的路径,可以看到熟悉的swagger风格接口文档

通过增加注解的方式,可以对API的页面展示进行管理,以下是GET参数的配置方式

class RestUserListView(APIView):
    @swagger_auto_schema(tags=['功能模块一'], operation_summary='功能模块简介', manual_parameters=[
        # 使用manual_parameters定义GET参数
        openapi.Parameter('param1', openapi.IN_QUERY, type=openapi.TYPE_STRING, description='param1'),
        openapi.Parameter('param2', openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description='param2'),
        openapi.Parameter('param3', openapi.IN_QUERY, type=openapi.TYPE_STRING, description='param3'),
    ])
    def get(self, request):
        ...

POST参数可以配置成DRF的Serializer,也可以手动写,以下是个提交数据列表并变更状态的示例,

class UpdateStatusView(APIView):
    @swagger_auto_schema(tags=['功能模块一'], operation_summary='更新状态', manual_parameters=[
        openapi.Parameter('version', openapi.IN_QUERY, type=openapi.TYPE_STRING, description='版本'),
    ], request_body=openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(
        type=openapi.TYPE_OBJECT, properties={
            'id': openapi.Schema(type=openapi.TYPE_STRING),
            'status': openapi.Schema(type=openapi.TYPE_INTEGER),
            'timestamp': openapi.Schema(type=openapi.TYPE_INTEGER),
        })))
    def post(self, request):
        ...

如果使用DRF的Serializer类,只需把request_body参数配置成指定的Serializer类

...
request_body=MyDataSerializer
...

如果某些接口不需要在文档中展示,在注解中传递空对象

class HiddenAPIView(APIView):
    @swagger_auto_schema(auto_schema=None)
    def post(self, request):
        ...

分割线 – 2025/9/25 – 其他特殊用法持续更新

上面都是针对JSON的请求,以下是Form请求的写法,使用了DRF的解析类 FormParser

class BaseLoginView(APIView):
    parser_classes = [FormParser]  # 解析类 FormParser
    @swagger_auto_schema(tags=['登录', ], operation_summary='用户名密码登录', manual_parameters=[
        # 自定义参数,类型是 openapi.IN_FORM
        openapi.Parameter('useraname', openapi.IN_FORM, type=openapi.TYPE_STRING, description='用户名'),
        openapi.Parameter('password', openapi.IN_FORM, type=openapi.TYPE_STRING, description='密码'),
        openapi.Parameter('captcha', openapi.IN_FORM, type=openapi.TYPE_STRING, description='验证码'),
    ])
    def post(self, request):
        ...

以下是文件上传的写法:

class UploadView(APIView):
    """上传图片"""
    parser_classes = [MultiPartParser, ]   #解析类 MultiPartParser
    @swagger_auto_schema(operation_summary='上传图片', tags=['【基础服务】'], manual_parameters=[
        # 类型使用 openapi.TYPE_FILE,代表文件
        openapi.Parameter('file', openapi.IN_FORM, type=openapi.TYPE_FILE, required=True, description='文件上传'),
        openapi.Parameter('timestamp', openapi.IN_FORM, type=openapi.TYPE_INTEGER, required=True, description='时间'),
    ])
    def post(self, request):
        ...

以上就是我常用的几种写法, GET参数 type=openapi.IN_QUERY, HEADER参数 type=openapi.IN_HEADER,

POST参数时,如果用FORM请求 type=openapi.IN_FORM,

JSON请求使用requestBody=… 可以使用自定义的openapi.TYPE_OBJECT, openapi.TYPE_ARRAY,也可以直接使用Serializer类

文档中也有关于response的定义,我很少用到。

2025/9/26 于 北京 上东廓

这篇文章有用吗?

点击星号为它评分!

平均评分 0 / 5. 投票数: 0

到目前为止还没有投票!成为第一位评论此文章。

很抱歉,这篇文章对您没有用!

让我们改善这篇文章!

告诉我们我们如何改善这篇文章?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注