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 链接和操作 memcache方法
Mar 04 Python
python简单实例训练(21~30)
Nov 15 Python
使用sklearn进行对数据标准化、归一化以及将数据还原的方法
Jul 11 Python
初探利用Python进行图文识别(OCR)
Feb 26 Python
python脚本实现mp4中的音频提取并保存在原目录
Feb 27 Python
Python并发concurrent.futures和asyncio实例
May 04 Python
python 解决Fatal error in launcher:错误问题
May 21 Python
tensorflow 动态获取 BatchSzie 的大小实例
Jun 30 Python
Python如何读写CSV文件
Aug 13 Python
python 从list中随机取值的方法
Nov 16 Python
如何理解python接口自动化之logging日志模块
Jun 15 Python
浅谈Python中的正则表达式
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 和 XML: 使用expat函数(一)
2006/10/09 PHP
IIS安装Apache伪静态插件的具体操作图文
2013/07/01 PHP
PHP Streams(流)详细介绍及使用
2015/05/12 PHP
PHP简单操作MongoDB的方法(安装及增删改查)
2016/05/26 PHP
javascript window对象属性整理
2009/10/24 Javascript
jquery判断元素是否隐藏的多种方法
2014/05/06 Javascript
推荐JavaScript实现继承的最佳方式
2014/11/11 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
jquery 重写 ajax提交并判断权限后 使用load方法报错解决方法
2016/01/19 Javascript
AngularJS基础 ng-mousemove 指令简单示例
2016/08/02 Javascript
聊一聊jQuery插件uploadify使用方法
2016/08/24 Javascript
详解如何使用webpack在vue项目中写jsx语法
2017/11/08 Javascript
Angular中点击li标签实现更改颜色的核心代码
2017/12/08 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(下)
2018/04/18 Javascript
在小程序/mpvue中使用flyio发起网络请求的方法
2018/09/13 Javascript
在Vuex使用dispatch和commit来调用mutations的区别详解
2018/09/18 Javascript
vue实现多个元素或多个组件之间动画效果
2018/09/25 Javascript
vue 配置多页面应用的示例代码
2018/10/22 Javascript
小程序实现列表多个批量倒计时
2021/01/29 Javascript
Angular7中创建组件/自定义指令/管道的方法实例详解
2019/04/02 Javascript
小程序实现分类页
2019/07/12 Javascript
vue.js 实现a标签href里添加参数
2019/11/12 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
2020/08/31 Javascript
列举Python中吸引人的一些特性
2015/04/09 Python
Python函数式编程指南(二):从函数开始
2015/06/24 Python
Python实现KNN邻近算法
2021/01/28 Python
Python实现九宫格式的朋友圈功能内附“马云”朋友圈
2019/05/07 Python
Python进程,多进程,获取进程id,给子进程传递参数操作示例
2019/10/11 Python
解决Python二维数组赋值问题
2019/11/28 Python
Python实现剪刀石头布小游戏(与电脑对战)
2019/12/31 Python
浅谈pytorch、cuda、python的版本对齐问题
2020/01/15 Python
viagogo英国票务平台:演唱会、体育比赛、戏剧门票
2017/03/24 全球购物
美国最大的旗帜经销商:Carrot-Top
2018/02/26 全球购物
HEMA英国:荷兰原创设计
2018/08/28 全球购物
初中语文教学反思
2014/02/02 职场文书
java如何实现socket连接方法封装
2021/09/25 Java/Android