Django REST Swagger实现指定api参数


Posted in Python onJuly 07, 2020

为什么要指定swagger的api参数

api的参数有多种类型:

query 参数,如 /users?role=admin

path 参数,如 /users/{id}

header 参数,如 X-MyHeader: Value

body 参数,描述POST,PUT,PATCH请求的body

form 参数,描述 Content-Type of application/x-www-form-urlencoded 和 multipart/form-data 的请求报文body的参数

swagger指定api参数就可以在文档相应的api条目中显示出api的描述、正常输出、异常输出、参数的名称、描述、是否必填、值类型、参数类型对不同的参数类型有不同的显示效果。swagger是可交互的api文档,可以直接填入文档显示的参数的值并发送请求,返回的结果就会在文档中显示。

Django REST Swagger实现指定api参数

难点

对 Django REST Swagger < 2 的版本,要指定swagger的api参数非常容易,只要将相关说明以特定格式和yaml格式写在相应api的视图函数的文档字符串(DocStrings)里,swagger就会自动渲染到文档中。比如这样的格式:

def cancel(self, request, id):
 """
 desc: 取消任务,进行中的参与者得到报酬
 ret: msg
 err: 404页面/msg
 input:
 - name: id
 desc: 任务id
 type: string
 required: true
 location: path
 """

但是在2.0版本之后,Django REST Swagger废弃了对yaml文档字符串的支持,不会渲染出任何内容。

一种解决方案

在Django REST framework基于类的api视图中定义filter_class过滤出模型(models)的特定字段,swagger会根据这些字段来渲染。

from django_filters.rest_framework.filterset import FilterSet

class ProductFilter(FilterSet):

 class Meta(object):
 models = models.Product
 fields = (
  'name', 'category', 'id', )

class PurchasedProductsList(generics.ListAPIView):
 """
 Return a list of all the products that the authenticated
 user has ever purchased, with optional filtering.
 """
 model = Product
 serializer_class = ProductSerializer
 filter_class = ProductFilter

 def get_queryset(self):
 user = self.request.user
 return user.purchase_set.all()

这个解决方法只解决了一半问题,只能用在面向模型的api,只能过滤模型的一些字段,而且api参数名与模型字段名不一致时还要额外处理。

启发

查阅Django REST Swagger的文档,Advanced Usage提到,基于类的文档api视图是这样的:

from rest_framework.response import Response
from rest_framework.schemas import SchemaGenerator
from rest_framework.views import APIView
from rest_framework_swagger import renderers

class SwaggerSchemaView(APIView):
 permission_classes = [AllowAny]
 renderer_classes = [
 renderers.OpenAPIRenderer,
 renderers.SwaggerUIRenderer
 ]

 def get(self, request):
 generator = SchemaGenerator()
 schema = generator.get_schema(request=request)

 return Response(schema)

说明文档是根据schema变量来渲染的,所以可以通过重载schema变量,利用yaml包解析出api视图函数的文档字符串中的参数定义赋值给schema变量。

更好的解决方法

创建schema_view.py:

from django.utils.six.moves.urllib import parse as urlparse
from rest_framework.schemas import AutoSchema
import yaml
import coreapi
from rest_framework_swagger.views import get_swagger_view

class CustomSchema(AutoSchema):
 def get_link(self, path, method, base_url):

 view = self.view
 method_name = getattr(view, 'action', method.lower())
 method_docstring = getattr(view, method_name, None).__doc__
 _method_desc = ''

 fields = self.get_path_fields(path, method)

 try:
  a = method_docstring.split('---')
 except:
  fields += self.get_serializer_fields(path, method)
 else:
  yaml_doc = None
  if method_docstring:
  try:
   yaml_doc = yaml.load(a[1])
  except:
   yaml_doc = None

  # Extract schema information from yaml

  if yaml_doc and type(yaml_doc) != str:
  _desc = yaml_doc.get('desc', '')
  _ret = yaml_doc.get('ret', '')
  _err = yaml_doc.get('err', '')
  _method_desc = _desc + '\n<br/>' + 'return: ' + _ret + '<br/>' + 'error: ' + _err
  params = yaml_doc.get('input', [])

  for i in params:
   _name = i.get('name')
   _desc = i.get('desc')
   _required = i.get('required', False)
   _type = i.get('type', 'string')
   _location = i.get('location', 'form')
   field = coreapi.Field(
   name=_name,
   location=_location,
   required=_required,
   description=_desc,
   type=_type
   )
   fields.append(field)
  else:
  _method_desc = a[0]
  fields += self.get_serializer_fields(path, method)

 fields += self.get_pagination_fields(path, method)
 fields += self.get_filter_fields(path, method)

 manual_fields = self.get_manual_fields(path, method)
 fields = self.update_fields(fields, manual_fields)

 if fields and any([field.location in ('form', 'body') for field in fields]):
  encoding = self.get_encoding(path, method)
 else:
  encoding = None

 if base_url and path.startswith('/'):
  path = path[1:]

 return coreapi.Link(
  url=urlparse.urljoin(base_url, path),
  action=method.lower(),
  encoding=encoding,
  fields=fields,
  description=_method_desc
 )

schema_view = get_swagger_view(title='API')

urls.py中指向schema_view:

from .schema_view import schema_view

urlpatterns = [
 url(r'^v1/api/', include([
 url(r'^doc/', schema_view),
 ])),

然后在需要指定api参数的视图类(如APIView或ModelViewSet)中重载schema:

schema = CustomSchema()

以上这篇Django REST Swagger实现指定api参数就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中numpy基础学习及进行数组和矢量计算
Feb 12 Python
Python实现将罗马数字转换成普通阿拉伯数字的方法
Apr 19 Python
Python实现图片拼接的代码
Jul 02 Python
解决pandas中读取中文名称的csv文件报错的问题
Jul 04 Python
Sanic框架配置操作分析
Jul 17 Python
Python 访问限制 private public的详细介绍
Oct 16 Python
Django rest framework jwt的使用方法详解
Aug 08 Python
基于MATLAB和Python实现MFCC特征参数提取
Aug 13 Python
Python socket实现的文件下载器功能示例
Nov 15 Python
解决python执行较大excel文件openpyxl慢问题
May 15 Python
python计算auc的方法
Sep 09 Python
如何利用Python实现一个论文降重工具
Jul 09 Python
python中查看.db文件中表格的名字及表格中的字段操作
Jul 07 #Python
python db类用法说明
Jul 07 #Python
python文件编写好后如何实践
Jul 07 #Python
python 删除excel表格重复行,数据预处理操作
Jul 06 #Python
pandas.DataFrame.drop_duplicates 用法介绍
Jul 06 #Python
TensorFlow Autodiff自动微分详解
Jul 06 #Python
Keras loss函数剖析
Jul 06 #Python
You might like
php生成缩略图填充白边(等比缩略图方案)
2013/12/25 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
jquery中:input和input的区别分析
2011/07/13 Javascript
从jQuery.camelCase()学习string.replace() 函数学习
2011/09/13 Javascript
jquery实现手风琴效果实例代码
2013/11/15 Javascript
利用函数的惰性载入提高javascript代码执行效率
2014/05/05 Javascript
基于javascript实现页面加载loading效果
2020/09/15 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
vuex实现简易计数器
2016/10/27 Javascript
JS实现DIV高度自适应窗口示例
2017/02/16 Javascript
深入理解Vue 的条件渲染和列表渲染
2017/09/01 Javascript
VUE中的无限循环代码解析
2017/09/22 Javascript
深入剖析Express cookie-parser中间件实现示例
2018/02/01 Javascript
vue权限路由实现的方法示例总结
2018/07/29 Javascript
30分钟用Node.js构建一个API服务器的步骤详解
2019/05/24 Javascript
教你完全理解ReentrantLock重入锁
2019/06/03 Javascript
解决layui表格的表头不滚动的问题
2019/09/04 Javascript
Vue3.0中的monorepo管理模式的实现
2019/10/14 Javascript
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
Python发送http请求解析返回json的实例
2018/03/26 Python
python 将数据保存为excel的xls格式(实例讲解)
2018/05/03 Python
Python 合并拼接字符串的方法
2020/07/28 Python
Python趣味入门教程之循环语句while
2020/08/26 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
css3截图_动力节点Java学院整理
2017/07/11 HTML / CSS
泰国折扣酒店预订:Hotels2Thailand
2018/03/20 全球购物
英国乐购杂货:Tesco Groceries
2018/11/29 全球购物
美国摩托车头盔、零件、齿轮及配件商店:Cycle Gear
2019/06/12 全球购物
留学自荐信的技巧
2013/10/17 职场文书
小学生纪念九一八事变演讲稿
2014/09/14 职场文书
手机被没收的检讨书
2014/10/04 职场文书
党员学习型组织心得体会
2019/06/21 职场文书
python 自动化偷懒的四个实用操作
2021/04/11 Python
PyTorch 如何自动计算梯度
2021/05/23 Python
Ubuntu Server 安装Tomcat并配置systemctl
2022/04/28 Servers
MySQL 执行数据库更新update操作的时候数据库卡死了
2022/05/02 MySQL