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 多线程的实例详解
Sep 07 Python
numpy 进行数组拼接,分别在行和列上合并的实例
May 08 Python
使用k8s部署Django项目的方法步骤
Jan 14 Python
在Pycharm中调试Django项目程序的操作方法
Jul 17 Python
python 中值滤波,椒盐去噪,图片增强实例
Dec 18 Python
深入了解如何基于Python读写Kafka
Dec 31 Python
tensorflow生成多个tfrecord文件实例
Feb 17 Python
什么是python的id函数
Jun 11 Python
python实现二分查找算法
Sep 18 Python
python实现逻辑回归的示例
Oct 09 Python
Python图像处理之图像拼接
Apr 28 Python
如何利用python实现Simhash算法
Jun 28 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开发负载均衡指南
2010/07/17 PHP
PHP获取浏览器信息类和客户端地理位置的2个方法
2014/04/24 PHP
destoon二次开发入门示例
2014/06/20 PHP
php显示指定目录下子目录的方法
2015/03/20 PHP
PHP易混淆知识整理笔记
2015/09/24 PHP
js实现DIV的一些简单控制
2007/06/04 Javascript
javascript的trim,ltrim,rtrim自定义函数
2008/09/21 Javascript
javascript多种数据类型表格排序代码分析
2010/09/11 Javascript
JQuery实现简单验证码提示解决方案
2012/12/20 Javascript
判断一个变量是数组Array类型的方法
2013/09/16 Javascript
使用jquery+CSS实现控制打印样式
2014/12/31 Javascript
JS数组合并push与concat区别分析
2015/12/17 Javascript
微信小程序 Image API实例详解
2016/09/30 Javascript
Angular 4依赖注入学习教程之InjectToken的使用(八)
2017/06/04 Javascript
详解利用jsx写vue组件的方法示例
2017/07/17 Javascript
js中的闭包学习心得
2018/02/06 Javascript
微信小程序实现带缩略图轮播效果
2018/11/04 Javascript
JS实现水平遍历和嵌套递归操作示例
2019/08/15 Javascript
JS实现商品橱窗特效
2020/01/09 Javascript
Python 文件操作技巧(File operation) 实例代码分析
2008/08/11 Python
Python自动连接ssh的方法
2015/03/07 Python
Python中super关键字用法实例分析
2015/05/28 Python
Python中捕获键盘的方式详解
2019/03/28 Python
浅谈python中频繁的print到底能浪费多长时间
2020/02/21 Python
python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)
2020/04/08 Python
深入了解python列表(LIST)
2020/06/08 Python
德国户外装备、登山运动和攀岩商店:tapir store
2020/02/12 全球购物
Zatchels官网:英国剑桥包品牌
2021/01/12 全球购物
机械专业应届生求职信
2013/09/21 职场文书
考试不及格检讨书
2014/01/09 职场文书
互联网创业计划书的书写步骤
2014/01/28 职场文书
职员竞岗演讲稿
2014/05/14 职场文书
二手车交易协议书标准版
2014/11/16 职场文书
2014年社区宣传工作总结
2014/12/02 职场文书
2014年药品销售工作总结
2014/12/16 职场文书
与死神共舞观后感
2015/06/15 职场文书