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实现类似ftp传输文件的网络程序示例
Apr 08 Python
python 捕获 shell/bash 脚本的输出结果实例
Jan 04 Python
python复制文件到指定目录的实例
Apr 27 Python
django 微信网页授权认证api的步骤详解
Jul 30 Python
Python获取统计自己的qq群成员信息的方法
Nov 15 Python
Tensorflow之梯度裁剪的实现示例
Mar 08 Python
python 一维二维插值实例
Apr 22 Python
aws 通过boto3 python脚本打pach的实现方法
May 10 Python
基于Python脚本实现邮件报警功能
May 20 Python
Python Tricks 使用 pywinrm 远程控制 Windows 主机的方法
Jul 21 Python
Node.js 和 Python之间该选择哪个?
Aug 05 Python
Python实现视频自动打码的示例代码
Apr 08 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
基于Zend的Config机制的应用分析
2013/05/02 PHP
php获取网页请求状态程序示例
2014/06/17 PHP
php生成毫秒时间戳的实例讲解
2017/09/22 PHP
PHP实现网站访问量计数器
2017/10/27 PHP
基于jquery的finkyUI插件与Ajax实现页面数据加载功能
2010/12/03 Javascript
js替代copy(示例代码)
2013/11/27 Javascript
js读取json的两种常用方法示例介绍
2014/10/19 Javascript
jQuery+canvas实现简单的球体斜抛及颜色动态变换效果
2016/01/28 Javascript
使用 stylelint检查CSS_StyleLint
2016/04/28 Javascript
基于javascript实现数字英文验证码
2017/01/25 Javascript
Vue前端开发规范整理(推荐)
2018/04/23 Javascript
微信小程序常用简易小函数总结
2019/02/01 Javascript
vue组件之间的数据传递方法详解
2019/04/19 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
Python中if __name__ == &quot;__main__&quot;详细解释
2014/10/21 Python
Python2.6版本中实现字典推导 PEP 274(Dict Comprehensions)
2015/04/28 Python
python 获取指定文件夹下所有文件名称并写入列表的实例
2018/04/23 Python
利用pyinstaller将py文件打包为exe的方法
2018/05/14 Python
Python使用progressbar模块实现的显示进度条功能
2018/05/31 Python
Python实现的txt文件去重功能示例
2018/07/07 Python
PyTorch预训练的实现
2019/09/18 Python
基于Python批量生成指定尺寸缩略图代码实例
2019/11/20 Python
解决导入django_filters不成功问题No module named 'django_filter'
2020/07/15 Python
Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)
2021/01/29 Python
意大利大型购物中心:Oliviero.it
2017/10/19 全球购物
室内设计自我鉴定
2013/10/15 职场文书
五年级科学教学反思
2014/02/05 职场文书
民族团结演讲稿范文
2014/08/27 职场文书
科级干部群众路线教育实践活动个人对照检查材料
2014/09/19 职场文书
2014年为民办实事工作总结
2014/12/20 职场文书
运动会运动员赞词
2015/07/22 职场文书
七年级数学教学反思
2016/02/17 职场文书
在Windows下安装配置CPU版的PyTorch的方法
2021/04/02 Python
如何用JavaScript学习算法复杂度
2021/04/30 Javascript
Python实现单例模式的5种方法
2021/06/15 Python
浅谈Python实现opencv之图片色素的数值运算和逻辑运算
2021/06/23 Python