django配置swagger自动生成接口文档以及自定义参数设置
阅读原文时间:2023年08月25日阅读:4

  首先安装swagger所用的包

pip install drf-yasg

  然后再settings.py 中注册app

  

  接口采用的token认证,在settings.py配置认证方式

SWAGGER_SETTINGS = {
'USE_SESSION_AUTH': False,
'SECURITY_DEFINITIONS': {
'身份验证': {
'type': 'apiKey',
'in': 'header',
'name': 'Authorization'
}
},
}

  配好后打开的认证是这样的

  在urls.py中配置路由

from django.contrib import admin
from django.urls import path, include

使用 drf_yasg API文档生成器 视图和openapi

from django.views.static import serve
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

导入权限控制模块

from rest_framework import permissions

文档视图

schema_view = get_schema_view(
# API 信息
openapi.Info(
title='接口文档', # API文档标题
default_version='V1', # 版本信息
description='接口文档', # 描述内容
# terms_of_service='https://qaq.com', # 开发团队地址
# contact=openapi.Contact(email='https://qaq.@qq.com',url='https://qaq.com'), # 联系人信息:邮件、网址
# license=openapi.License(name='qaq License'), # 证书
),
public=True, # 是否公开
# permission_classes=(permissions.AllowAny,) # 设置用户权限

)

urlpatterns = [
path('admin/', admin.site.urls),

path('userManage/', include('userManage.urls')),  
path('ani/', include('ani.urls')),

path('swagger/', schema\_view.with\_ui('swagger', cache\_timeout=0), name='schema-swagger-ui'),   # 互动模式  
path('redoc/', schema\_view.with\_ui('redoc', cache\_timeout=0), name='schema-redoc'),   # 文档模式  

]

  配置好以后打开  http://127.0.0.1:8000/swagger/即可访问到接口文档页面

  打开查看后发现,请求的参数缺少了,返回的参数和接口实际返回的参数不一样,因为我的视图继承APIView做了一些自定义的请求参数和返回参数。

  所以需要自定义swagger

  util.py文件,因为自动生成的采用序列化 query_serializer参数就会将一些外键的source字段也加到参数里面,所以重新去获取序列器的字段。再定义一个

  固定格式的基类

from rest_framework import serializers
from drf_yasg import openapi
from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.fields import ChoiceField

def serializer_to_swagger(ser_model, get_req=False):
'''
将序列化字段转成openapi的形式
'''
if ser_model is None and get_req is True:
return {}, []
elif ser_model is None and get_req is False:
return {}
dit = {}
serializer_field_mapping = {
ChoiceField: openapi.TYPE_INTEGER,
PrimaryKeyRelatedField: openapi.TYPE_INTEGER,
serializers.IntegerField: openapi.TYPE_INTEGER,
serializers.BooleanField: openapi.TYPE_BOOLEAN,
serializers.CharField: openapi.TYPE_STRING,
serializers.DateField: openapi.TYPE_STRING,
serializers.DateTimeField: openapi.TYPE_STRING,
serializers.DecimalField: openapi.TYPE_NUMBER,
serializers.DurationField: openapi.TYPE_STRING,
serializers.EmailField: openapi.TYPE_STRING,
serializers.ModelField: openapi.TYPE_OBJECT,
serializers.FileField: openapi.TYPE_STRING,
serializers.FloatField: openapi.TYPE_NUMBER,
serializers.ImageField: openapi.TYPE_STRING,
serializers.SlugField: openapi.TYPE_STRING,
serializers.TimeField: openapi.TYPE_STRING,
serializers.URLField: openapi.TYPE_STRING,
serializers.UUIDField: openapi.TYPE_STRING,
serializers.IPAddressField: openapi.TYPE_STRING,
serializers.FilePathField: openapi.TYPE_STRING,
}
fields = ser_model().get_fields()
if get_req:
required = []
for k, v in fields.items():
description = getattr(v, 'label', '')
if isinstance(v, serializers.SerializerMethodField) or getattr(v, 'source'):
continue
elif isinstance(v, ChoiceField):
description += str(dict(getattr(v, 'choices', {})))
if getattr(v, 'required', True) is not False:
required.append(k)
typ = serializer_field_mapping.get(type(v), openapi.TYPE_STRING)
dit[k] = openapi.Schema(description=description, type=typ)
return dit, required
else:
for k, v in fields.items():
description = getattr(v, 'label', '')
if isinstance(v, ChoiceField):
description += str(dict(getattr(v, 'choices', {})))
elif isinstance(v, serializers.SerializerMethodField):
continue
typ = serializer_field_mapping.get(type(v), openapi.TYPE_STRING)
dit[k] = openapi.Schema(description=description, type=typ)

    return dit

class ViewSwagger(object):
"""
openapi视图类
重写请求参数和返回参数,调用对应的类方法即可
"""

get\_operation = '获取数据'  
get\_req\_params = \[\]  
get\_req\_body = None  
get\_res\_data = None  
get\_res\_examples = {'json': {}}  
get\_res\_description = ' '  
get\_res\_code = 200

post\_operation = '新增数据'  
post\_req\_params = \[\]  
post\_req\_body = None  
post\_res\_data = None  
post\_res\_examples = {'json': {}}  
post\_res\_description = ' '  
post\_res\_code = 200

put\_operation = '修改数据'  
put\_req\_params = \[\]  
put\_req\_body = None  
put\_res\_data = None  
put\_res\_examples = {'json': {}}  
put\_res\_description = ' '  
put\_res\_code = 200

delete\_operation = '删除数据'  
delete\_req\_params = \[\]  
delete\_req\_body = None  
delete\_res\_data = None  
delete\_res\_examples = {'json': {}}  
delete\_res\_description = ' '  
delete\_res\_code = 200

@classmethod  
def req\_serialize\_schema(cls, serializer):  
    return serializer\_to\_swagger(serializer, get\_req=True)

@classmethod  
def res\_serialize\_schema(cls, serializer):  
    return serializer\_to\_swagger(serializer, get\_req=False)

@classmethod  
def get(cls):  
    ret = {  
        'manual\_parameters': cls.get\_req\_params,  
        'request\_body': cls.get\_req\_body,  
        'operation\_summary': cls.get\_operation,  
        'responses': {  
            cls.get\_res\_code: openapi.Response(description=cls.get\_res\_description, schema=cls.get\_res\_data,  
                                               examples=cls.get\_res\_examples)}  
    }  
    return ret

@classmethod  
def post(cls):  
    ret = {  
        'manual\_parameters': cls.post\_req\_params,  
        'request\_body': cls.post\_req\_body,  
        'operation\_summary': cls.post\_operation,  
        'responses': {  
            cls.post\_res\_code: openapi.Response(description=cls.post\_res\_description, schema=cls.post\_res\_data,  
                                                examples=cls.post\_res\_examples)}  
    }  
    return ret

@classmethod  
def put(cls):  
    ret = {  
        'manual\_parameters': cls.put\_req\_params,  
        'request\_body': cls.put\_req\_body,  
        'operation\_summary': cls.put\_operation,  
        'responses': {  
            cls.put\_res\_code: openapi.Response(description=cls.put\_res\_description, schema=cls.put\_res\_data,  
                                               examples=cls.put\_res\_examples)}  
    }  
    return ret

@classmethod  
def delete(cls):  
    ret = {  
        'manual\_parameters': cls.delete\_req\_params,  
        'request\_body': cls.delete\_req\_body,  
        'operation\_summary': cls.delete\_operation,  
        'responses': {  
            cls.delete\_res\_code: openapi.Response(description=cls.delete\_res\_description,  
                                                  schema=cls.delete\_res\_data,  
                                                  examples=cls.delete\_res\_examples)}  
    }  
    return ret

  下面只要在视图中单独定义对应的字段即可,gender.py 如下

import copy

from django.utils.decorators import method_decorator

from ani import models
from ani.serializer import GenderSerializer
from utils.decorators import request_decrypt, auth_token
from utils.myView import MyPagination, MyView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, \
MixinDeleteDestroyModel

from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from utils.util import ViewSwagger

class APISwagger(ViewSwagger):
serializer = GenderSerializer
res_ser_schema = ViewSwagger.res_serialize_schema(serializer)
req_ser_schema, req_ser_required_fields = ViewSwagger.req_serialize_schema(serializer)
get_operation = '获取数据'
get_req_params = [
openapi.Parameter(name='name__icontains', in_=openapi.IN_QUERY, description='过滤包含该字段', type=openapi.TYPE_STRING,
required=False),
]
get_req_body = None
get_res_data = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'data': openapi.Schema(description='', type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_OBJECT, properties={
**res_ser_schema
})),
'total': openapi.Schema(description='总数', type=openapi.TYPE_INTEGER),
})
get_res_examples = {'json': {}}
get_res_description = 'get返回'
get_res_code = 200

post\_schema = copy.copy(req\_ser\_schema)  
del post\_schema\['id'\]  
post\_operation = '新增数据'  
post\_req\_params = \[\]  
post\_req\_body = openapi.Schema(  
        type=openapi.TYPE\_OBJECT,  
        properties={  
            \*\*post\_schema  
            },  
        required=req\_ser\_required\_fields  
    )  
post\_res\_data = openapi.Schema(type=openapi.TYPE\_OBJECT, properties={  
            \*\*res\_ser\_schema  
    })  
post\_res\_examples = {'json': {}}  
post\_res\_description = ' '  
post\_res\_code = 200

put\_fields = req\_ser\_required\_fields  
put\_fields.append('id')  
put\_operation = '新增数据'  
put\_req\_params = \[\]  
put\_req\_body = openapi.Schema(  
    type=openapi.TYPE\_OBJECT,  
    properties={  
        \*\*req\_ser\_schema  
    },  
    required=put\_fields  
)  
put\_res\_data = openapi.Schema(type=openapi.TYPE\_OBJECT, properties={  
    \*\*res\_ser\_schema  
})  
put\_res\_examples = {'json': {}}  
put\_res\_description = ' '  
put\_res\_code = 200

@method_decorator([swagger_auto_schema(**APISwagger.delete())], name='delete')
@method_decorator([swagger_auto_schema(**APISwagger.put())], name='put')
@method_decorator([swagger_auto_schema(**APISwagger.post())], name='post')
@method_decorator([swagger_auto_schema(**APISwagger.get())], name='get')

@method_decorator(auth_token, name='get')

class GenderView(MyView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, MixinDeleteDestroyModel):
"""
get:
查询
post:
新增
put:
修改
delete:
删除

"""  
queryset = models.Gender.objects.all()  
serializer\_class = GenderSerializer  
all\_serializer\_class = GenderSerializer  
filter\_class = \['name\_\_icontains'\]  
pagination\_class = MyPagination  
lookup\_field = 'id'  
ordeing\_field = ('-id',)

  打开的接口文档变成

  try it out 调用接口,得到一样的数据

  注意:如果是post请求提交表单数据的时候,那么这个视图只能解析  parser_classes = [MultiPartParser],自定义的字段和get请求差不多,只需要将 _in=openapi.IN_FORM  即可

  项目文件结构

    

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章