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 相关文章推荐
Linux中Python 环境软件包安装步骤
Mar 31 Python
异步任务队列Celery在Django中的使用方法
Jun 07 Python
详解Django+Uwsgi+Nginx的生产环境部署
Jun 25 Python
Python 3.x基于Xml数据的Http请求方法
Dec 28 Python
Django restframework 源码分析之认证详解
Feb 22 Python
python 直接赋值和copy的区别详解
Aug 07 Python
python根据多个文件名批量查找文件
Aug 13 Python
详解Python3 pickle模块用法
Sep 16 Python
Django实现网页分页功能
Oct 31 Python
Python Django form 组件动态从数据库取choices数据实例
May 19 Python
python基于openpyxl生成excel文件
Dec 23 Python
python爬取股票最新数据并用excel绘制树状图的示例
Mar 01 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
2006/12/13 PHP
php下实现农历日历的代码
2007/03/07 PHP
PHP操作文件方法问答
2007/03/16 PHP
php cookie的操作实现代码(登录)
2010/12/29 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
2013/08/07 PHP
浅析application/x-www-form-urlencoded和multipart/form-data的区别
2014/06/22 PHP
使用PHP把HTML生成PDF文件的几个开源项目介绍
2014/11/17 PHP
PHP实现原生态图片上传封装类方法
2016/11/08 PHP
php-fpm服务启动脚本的方法
2018/04/27 PHP
详解PHP实现支付宝小程序用户授权的工具类
2018/12/25 PHP
php生成HTML文件的类方法
2019/10/11 PHP
PhpStorm连接服务器并实现自动上传功能
2020/12/09 PHP
jquery和javascript的区别(常用方法比较)
2013/07/04 Javascript
javascript框架设计读书笔记之字符串的扩展和修复
2014/12/02 Javascript
jQuery实现强制cookie过期方法汇总
2015/05/22 Javascript
vue.js指令v-model使用方法
2017/03/20 Javascript
详解Node中导入模块require和import的区别
2017/08/11 Javascript
基于JQuery的Ajax方法使用详解
2017/08/16 jQuery
详解angularjs实现echart图表效果最简洁教程
2017/11/29 Javascript
Vue项目引进ElementUI组件的方法
2018/11/11 Javascript
node基于async/await对mysql进行封装
2019/06/20 Javascript
如何在vue中使用jointjs过程解析
2020/05/29 Javascript
Vue项目中数据的深度监听或对象属性的监听实例
2020/07/17 Javascript
js实现带有动画的返回顶部
2020/08/09 Javascript
[08:07]DOTA2每周TOP10 精彩击杀集锦vol.8
2014/06/25 DOTA
[02:33]2018DOTA2亚洲邀请赛赛前采访——LGD
2018/04/04 DOTA
python 把文件中的每一行以数组的元素放入数组中的方法
2018/04/29 Python
Windows下python3安装tkinter的问题及解决方法
2020/01/06 Python
Python测试框架:pytest学习笔记
2020/10/20 Python
python爬虫如何解决图片验证码
2021/02/14 Python
CSS3提交意见输入框样式代码
2014/10/30 HTML / CSS
应届毕业生的自我鉴定
2013/11/13 职场文书
受资助学生感谢信
2015/01/21 职场文书
对学校的意见和建议
2015/06/04 职场文书
实施意见格式范本
2015/06/05 职场文书
2016春季运动会开幕词
2016/03/04 职场文书