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复制与引用用法分析
Apr 08 Python
Python的Django框架使用入门指引
Apr 15 Python
常见的python正则用法实例讲解
Jun 21 Python
python字符串str和字节数组相互转化方法
Mar 18 Python
python爬虫获取京东手机图片的图文教程
Dec 29 Python
Python之循环结构
Jan 15 Python
Python面向对象程序设计类的封装与继承用法示例
Apr 12 Python
python 申请内存空间,用于创建多维数组的实例
Dec 02 Python
Python reques接口测试框架实现代码
Jul 28 Python
Python调用Redis的示例代码
Nov 24 Python
python 进制转换 int、bin、oct、hex的原理
Jan 13 Python
python数据可视化JupyterLab实用扩展程序Mito
Nov 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读取txt文件的内容并赋值给数组的代码
2011/11/03 PHP
PHPThumb PHP 图片缩略图库
2012/03/11 PHP
PHP入门之常量简介和系统常量
2014/05/12 PHP
php版微信公众平台入门教程之开发者认证的方法
2016/09/26 PHP
浅谈PHP的exec()函数无返回值排查方法(必看)
2017/03/31 PHP
javascript优先加载笔记代码
2008/09/30 Javascript
解决jquery submit()提交表单提示:f[s] is not a function
2013/01/23 Javascript
jQuery+.net实现浏览更多内容(改编php版本)
2013/03/28 Javascript
javascript自动给文本url地址增加链接的方法分享
2014/01/20 Javascript
jquery实现更改表格行顺序示例
2014/04/30 Javascript
推荐9款炫酷的基于jquery的页面特效
2014/12/07 Javascript
JavaScript 异常处理 详解
2015/02/06 Javascript
jQuery简单实现遍历数组的方法
2015/04/14 Javascript
Javascript实现图片不间断滚动的代码
2016/06/22 Javascript
JavaScript中闭包的写法和作用详解
2016/06/29 Javascript
jQuery 3.0 的 setter和getter 模式详解
2016/07/11 Javascript
js实现html table 行,列锁定的简单实例
2016/10/13 Javascript
Vue单页式应用(Hash模式下)实现微信分享的实例
2017/07/21 Javascript
微信小程序 上传头像的实例详解
2017/10/27 Javascript
vue vuex vue-rouert后台项目——权限路由(适合初学)
2017/12/29 Javascript
angular1配合gulp和bower的使用教程
2018/01/19 Javascript
node结合swig渲染摸板的方法
2018/04/11 Javascript
详解微信小程序缓存--缓存时效性
2019/05/02 Javascript
Python使用迭代器打印螺旋矩阵的思路及代码示例
2016/07/02 Python
pandas使用apply多列生成一列数据的实例
2018/11/28 Python
python仿抖音表白神器
2019/04/08 Python
Python实现将字符串的首字母变为大写,其余都变为小写的方法
2019/06/11 Python
django中使用Celery 布式任务队列过程详解
2019/07/29 Python
对python中的装包与解包实例详解
2019/08/24 Python
python pyqtgraph 保存图片到本地的实例
2020/03/14 Python
pytorch 中的重要模块化接口nn.Module的使用
2020/04/02 Python
Idea安装python显示无SDK问题解决方案
2020/08/12 Python
美国成衣女装品牌:CHICO’S
2016/09/19 全球购物
英国家庭、花园、汽车和移动解决方案:Easylife Group
2018/05/23 全球购物
大四学生思想汇报
2014/01/13 职场文书
群教个人对照检查材料
2014/08/20 职场文书