Django REST Swagger实现指定api参数

作者:Z_J_Q_ 时间:2023-03-10 05:48:58 

为什么要指定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()

来源:https://blog.csdn.net/Z_J_Q_/article/details/94205225

标签:Django,REST,Swagger,api
0
投稿

猜你喜欢

  • oracle 性能优化建议小结

    2010-04-22 16:32:00
  • Python列表list的详细用法介绍

    2021-04-17 06:56:15
  • 中国目前流行的网页设计风格

    2007-12-20 12:57:00
  • [译文]The seven rules of Unobtrusive JavaScript

    2008-09-29 12:10:00
  • Python Matplotlib初阶使用入门教程

    2022-03-17 21:02:33
  • 详解numpy矩阵的创建与数据类型

    2022-07-12 15:59:17
  • Python Web后端开发中的增查改删处理

    2022-11-21 06:15:42
  • Python的numpy库下的几个小函数的用法(小结)

    2021-12-13 10:29:33
  • 在Windows系统上搭建Nginx+Python+MySQL环境的教程

    2024-01-24 08:04:40
  • PHP合并两个或多个数组的方法

    2023-06-11 12:06:28
  • SQL Server 2005改进后的几个实用新特性

    2008-05-07 19:16:00
  • 详解Vue中添加过渡效果

    2024-04-27 16:04:29
  • PHP最常用的正则表达式

    2024-05-03 15:34:38
  • 在Python 中同一个类两个函数间变量的调用方法

    2022-07-02 04:53:57
  • Python基础之循环语句用法示例【for、while循环】

    2022-06-03 19:37:50
  • Python中如何替换字典中的值

    2022-10-04 21:21:35
  • Python实现Keras搭建神经网络训练分类模型教程

    2023-08-06 12:33:03
  • python游戏实战项目之智能五子棋简易版

    2021-02-06 21:32:56
  • 前端token中4个存储位置的优缺点说明

    2023-07-02 16:39:50
  • python3实现磁盘空间监控

    2023-07-09 14:12:49
  • asp之家 网络编程 m.aspxhome.com