首先安装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://[email protected]',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 即可
项目文件结构
标签:自定义,get,res,req,openapi,django,TYPE,参数设置,cls From: https://www.cnblogs.com/moon3496694/p/17657283.html