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实现2048小游戏
Mar 30 Python
python数据结构之图深度优先和广度优先实例详解
Jul 08 Python
在Python中移动目录结构的方法
Jan 31 Python
整理Python 常用string函数(收藏)
May 30 Python
利用Python破解验证码实例详解
Dec 08 Python
使用Python3制作TCP端口扫描器
Apr 17 Python
python进程管理工具supervisor的安装与使用教程
Sep 05 Python
Python调用服务接口的实例
Jan 03 Python
python爬取内容存入Excel实例
Feb 20 Python
Python 如何优雅的将数字转化为时间格式的方法
Sep 26 Python
教你如何使用Python开发一个钉钉群应答机器人
Jun 21 Python
python多次执行绘制条形图
Apr 20 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中多维数组的foreach遍历示例
2014/06/13 PHP
ThinkPHP访问不存在的模块跳转到404页面的方法
2014/06/19 PHP
个人写的PHP验证码生成类分享
2014/08/21 PHP
php程序内部post数据的方法
2015/03/31 PHP
PHP配置ZendOpcache插件加速
2019/02/14 PHP
Laravel登录失败次数限制的实现方法
2020/08/26 PHP
在textarea中显示html页面的javascript代码
2007/04/20 Javascript
javascript 仿QQ滑动菜单效果代码
2010/09/03 Javascript
js两行代码按指定格式输出日期时间
2011/10/21 Javascript
基于jquery编写的横向自适应幻灯片切换特效的实例代码
2013/08/06 Javascript
Extjs grid添加一个图片状态或者按钮的方法
2014/04/03 Javascript
jQuery学习笔记之jQuery原型属性和方法
2014/06/09 Javascript
超漂亮的Bootstrap 富文本编辑器summernote
2016/04/05 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
react性能优化达到最大化的方法 immutable.js使用的必要性
2017/03/09 Javascript
Angular如何引入第三方库的方法详解
2017/07/13 Javascript
快速将Vue项目升级到webpack3的方法步骤
2017/09/14 Javascript
JS使用正则表达式找出最长连续子串长度
2017/10/26 Javascript
一个Vue页面的内存泄露分析详解
2018/06/25 Javascript
jQuery each和js forEach用法比较
2019/02/27 jQuery
微信小程序中button去除默认的边框实例代码
2019/08/01 Javascript
解决vue中axios设置超时(超过5分钟)没反应的问题
2020/09/04 Javascript
[40:31]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python使用win32com库播放mp3文件的方法
2015/05/30 Python
使用python实现个性化词云的方法
2017/06/16 Python
Python中的延迟绑定原理详解
2019/10/11 Python
英国马莎百货官网:Marks & Spencer
2016/07/29 全球购物
美国领先的个性化礼品商城:Personalization Mall
2019/07/27 全球购物
Theflamel意大利:女士奢华服装、鞋子和配件
2020/01/11 全球购物
解释i节点在文件系统中的作用
2013/11/26 面试题
物流管理专业应届生求职信
2013/11/21 职场文书
工厂保洁员岗位职责
2013/12/04 职场文书
英语四级考试作弊检讨书
2014/09/29 职场文书
承租经营合作者协议书
2014/10/01 职场文书
企业三严三实学习心得体会
2014/10/13 职场文书
基于JavaScript实现省市联动效果
2021/06/22 Javascript