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 22 Python
Python使用Mechanize模块编写爬虫的要点解析
Mar 31 Python
Python设计足球联赛赛程表程序的思路与简单实现示例
Jun 28 Python
Python中内置的日志模块logging用法详解
Jul 12 Python
python 创建弹出式菜单的实现代码
Jul 11 Python
Python迭代器定义与简单用法分析
Apr 30 Python
Python3单行定义多个变量或赋值方法
Jul 12 Python
对Python信号处理模块signal详解
Jan 09 Python
详解PyTorch手写数字识别(MNIST数据集)
Aug 16 Python
Pycharm如何导入python文件及解决报错问题
May 10 Python
使用keras时input_shape的维度表示问题说明
Jun 29 Python
Python切片列表字符串如何实现切换
Aug 06 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
curl实现站外采集的方法和技巧
2014/01/31 PHP
php 批量添加多行文本框textarea一行一个
2014/06/03 PHP
PHP遍历XML文档所有节点的方法
2015/03/12 PHP
php微信公众平台开发之获取用户基本信息
2015/08/17 PHP
让回调函数 showResponse 也带上参数的代码
2007/08/13 Javascript
JavaScript 变量命名规则
2009/09/23 Javascript
javascript判断移动端访问设备并解析对应CSS的方法
2015/02/05 Javascript
理解javascript中Map代替循环
2016/02/26 Javascript
JavaScript数组方法总结分析
2016/05/06 Javascript
AngularJs 国际化(I18n/L10n)详解
2016/09/01 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
jQuery Autocomplete简介_动力节点Java学院整理
2017/07/17 jQuery
es6 字符串String的扩展(实例讲解)
2017/08/03 Javascript
Postman的下载及安装教程详解
2018/10/16 Javascript
深入了解JavaScript 私有化
2019/05/30 Javascript
解决layer 动态加载select 失效的问题
2019/09/18 Javascript
Python实现简单多线程任务队列
2016/02/27 Python
快速入手Python字符编码
2016/08/03 Python
Python实现基本数据结构中队列的操作方法示例
2017/12/04 Python
python中使用%与.format格式化文本方法解析
2017/12/27 Python
python文件写入write()的操作
2019/05/14 Python
python 初始化一个定长的数组实例
2019/12/02 Python
Django def clean()函数对表单中的数据进行验证操作
2020/07/09 Python
python爬虫beautifulsoup解析html方法
2020/12/07 Python
奥兰多迪士尼门票折扣:Undercover Tourist
2018/07/09 全球购物
师范应届毕业生自荐信
2013/11/18 职场文书
演讲稿开场白
2014/01/13 职场文书
四年级数学教学反思
2014/02/02 职场文书
培训楼经理岗位责任制
2014/02/10 职场文书
助人为乐好少年事迹材料
2014/08/18 职场文书
电力培训心得体会
2014/09/02 职场文书
集团财务总监岗位职责
2015/04/03 职场文书
老公出轨后的保证书
2015/05/08 职场文书
会议新闻稿
2015/07/17 职场文书
创业计划书之网吧
2019/10/10 职场文书
Python基础之元类详解
2021/04/29 Python