django-rest-framework 自定义swagger过程详解


Posted in Python onJuly 18, 2019

前言

之前的文章编写了一个返回json的例子,直接用浏览器进行get请求虽然成功了, 但是接口文档的样式很难看, 不好用. 而且提示没有访问权限.

我们一般都希望能够直接在接口文档中进行请求, 以测试接口, 本篇文章中会给出一个自定义swagger(openapi)的例子. 使接口文档变得美观可用, 可以填写参数, 可以进行请求以观察数据格式, 测试接口是否可用.

环境

workon python35
pip list
chardet (3.0.4)
coreapi (2.3.3)
coreschema (0.0.4)
Django (1.11.6)
django-rest-swagger (2.1.2)
django-simple-serializer (2.0.7)
djangorestframework (3.7.1)
future (0.16.0)
idna (2.6)
itypes (1.1.0)
Jinja2 (2.9.6)
MarkupSafe (1.0)
openapi-codec (1.3.2)
pip (9.0.1)
pytz (2017.2)
requests (2.18.4)
setuptools (36.6.0)
simplejson (3.11.1)
uritemplate (3.0.0)
urllib3 (1.22)
wheel (0.30.0)

阿里云的源中 最新版的django-rest-frmework版本为3.7.1

3.6 与 3.7的结构稍有不同. 我之前用3.6, 但是以下对swagger的修改以3.7.1版本为基准. 理解原理之后不同版本只需要稍作修改即可.

第一步修改配置

进入settings.py 文件, 确保INSTALLED_APPS中包含rest_framework

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'rest_framework',
  'rest_framework_swagger',
  'mytest',
]

我们导入了三个框架

  • rest_framework
  • rest_framework_swagger
  • mytest (之前的文章中编写简单接口的app)

然后在settings.py 文件中添加以下代码

REST_FRAMEWORK = {
  # 下面这一行表示接口文档的访问权限, AllowAny不做权限限制.
  'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
  # 'PAGE_SIZE': 10,
  'PAGINATE_BY':10,
}


SWAGGER_SETTINGS = {
  # 基础样式
  'SECURITY_DEFINITIONS': {
    "basic":{
      'type': 'basic'
    }
  },
  # 如果需要登录才能够查看接口文档, 登录的链接使用restframework自带的.
  'LOGIN_URL': 'rest_framework:login',
  'LOGOUT_URL': 'rest_framework:logout',
  # 'DOC_EXPANSION': None,
  # 'SHOW_REQUEST_HEADERS':True,
  # 'USE_SESSION_AUTH': True,
  # 'DOC_EXPANSION': 'list',
  # 接口文档中方法列表以首字母升序排列
  'APIS_SORTER': 'alpha',
  # 如果支持json提交, 则接口文档中包含json输入框
  'JSON_EDITOR': True,
  # 方法列表字母排序
  'OPERATIONS_SORTER': 'alpha',
  'VALIDATOR_URL': None,
}

第二步编写自定义的swagger接口文档页面.

思路:

之前urls.py中的接口文档页面来自这里

from rest_framework.schemas import get_schema_view

查看源码, 继承schema, 返回schema的子类即可.

接下来编写自己的schema

from rest_framework.permissions import AllowAny
from rest_framework.schemas import SchemaGenerator
from rest_framework.schemas.generators import LinkNode, insert_into
from rest_framework.renderers import *
from rest_framework_swagger import renderers
from rest_framework.response import Response

# from rest_framework.schemas import SchemaGenerator
class MySchemaGenerator(SchemaGenerator):

  def get_links(self, request=None):
    # from rest_framework.schemas.generators import LinkNode,
    links = LinkNode()

    paths = []
    view_endpoints = []
    for path, method, callback in self.endpoints:
      view = self.create_view(callback, method, request)
      path = self.coerce_path(path, method, view)
      paths.append(path)
      view_endpoints.append((path, method, view))

    # Only generate the path prefix for paths that will be included
    if not paths:
      return None
    prefix = self.determine_path_prefix(paths)

    for path, method, view in view_endpoints:
      if not self.has_view_permissions(path, method, view):
        continue
      link = view.schema.get_link(path, method, base_url=self.url)
      # 添加下面这一行方便在views编写过程中自定义参数.
      link._fields += self.get_core_fields(view)

      subpath = path[len(prefix):]
      keys = self.get_keys(subpath, method, view)

      # from rest_framework.schemas.generators import LinkNode, insert_into
      insert_into(links, keys, link)

    return links

  # 从类中取出我们自定义的参数, 交给swagger 以生成接口文档.
  def get_core_fields(self, view):
    return getattr(view, 'coreapi_fields', ())


class SwaggerSchemaView(APIView):
  _ignore_model_permissions = True
  exclude_from_schema = True

  # from rest_framework.permissions import AllowAny
  permission_classes = [AllowAny]
  # from rest_framework_swagger import renderers
  # from rest_framework.renderers import *
  renderer_classes = [
    CoreJSONRenderer,
    renderers.OpenAPIRenderer,
    renderers.SwaggerUIRenderer
  ]

  def get(self, request):
    generator = MySchemaGenerator(title='xxxxx',
                   description='''xxxxx''')

    schema = generator.get_schema(request=request)

    # from rest_framework.response import Response
    return Response(schema)

上面的代码中我加了注释, 写出了需要用到的一些方法, 参数, 类 都是从哪里import进来的.

上面的代码自定义了一个swagger页面, 加入了自定义参数的方法, 设置了访问权限(AllowAny), 添加了title和description,
原理, 其实就是继承父类, 重写方法以覆盖父类中的方法, 修改子类中overwrite的方法以添加我们想要的内容.

上面的代码其实写在哪里都可以, 找得到就行,我一般写在views.py 文件中和其他接口放在一起, 毕竟 http://xxxxx/docs/ 和/api/getjson 这样的接口一样都返回一个视图.

最后一步

修改urls.py文件, 把接口放出去.

from django.conf.urls import url, include
from django.contrib import admin
from rest_framework.schemas import get_schema_view
from mytest.views import ReturnJson
import mytest
# 下面是刚才自定义的schema
from mytest.views import SwaggerSchemaView

urlpatterns = [
  url(r'^admin/', admin.site.urls),
  url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
  url(r'^docs/', SwaggerSchemaView.as_view(), name='apiDocs'),
  url(r'^api/getjson', ReturnJson.as_view()),
]

注意上面我们添加了两个接口.

api-auth/和docs/

还记得配置文件中的他们吗

'LOGIN_URL': 'rest_framework:login',
'LOGOUT_URL': 'rest_framework:logout',

api-auth/就是为他俩准备的. 因为有时我们需要让接口文档登录之后才能够被看到..

最后运行项目看到

django-rest-framework 自定义swagger过程详解

剩下的问题

我们的第一个接口没有参数. 向接口文档的getjson接口添加一个参数.

修改 getjson接口对应的views.py文件中的类.ReturnJson类.

添加以下代码

def DocParam(name="default", location="query",
       required=True, description=None, type="string",
       *args, **kwargs):
  return coreapi.Field(name=name, location=location,
             required=required, description=description,
             type=type)


class ReturnJson(APIView):

  coreapi_fields=(
    DocParam("token"),
  )

  def get(self, request, *args, **kwargs):
    return JsonResponse("Hello world!!!!!!!!++++++中文测试")

这是所有的import

from django.shortcuts import render
from rest_framework.views import APIView
from dss.Serializer import serializer
from django.http import HttpResponse, HttpRequest
from rest_framework.permissions import AllowAny
from rest_framework.schemas import SchemaGenerator
from rest_framework.schemas.generators import LinkNode, insert_into
from rest_framework.renderers import *
from rest_framework_swagger import renderers
from rest_framework.response import Response
# from rest_framework.schemas import *

我也忘了. coreapi.Field是从哪里import的了....

以上代码为 getjson接口添加了token参数.

最终效果.

django-rest-framework 自定义swagger过程详解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python脚本对Linux服务器进行监控的教程
Apr 02 Python
Python常用随机数与随机字符串方法实例
Apr 09 Python
Python中几种操作字符串的方法的介绍
Apr 09 Python
目前最全的python的就业方向
Jun 05 Python
详解Django解决ajax跨域访问问题
Aug 24 Python
windows下numpy下载与安装图文教程
Apr 02 Python
Python实现的栈、队列、文件目录遍历操作示例
May 06 Python
python随机数分布random均匀分布实例
Nov 27 Python
pytorch torchvision.ImageFolder的用法介绍
Feb 20 Python
将tf.batch_matmul替换成tf.matmul的实现
Jun 18 Python
Python random模块的使用示例
Oct 10 Python
Python 中的Sympy详细使用
Aug 07 Python
django框架使用方法详解
Jul 18 #Python
Ubuntu+python将nii图像保存成png格式
Jul 18 #Python
python实现批量nii文件转换为png图像
Jul 18 #Python
django 捕获异常和日志系统过程详解
Jul 18 #Python
Django实现发送邮件功能
Jul 18 #Python
使用django的ORM框架按月统计近一年内的数据方法
Jul 18 #Python
Django框架之登录后自定义跳转页面的实现方法
Jul 18 #Python
You might like
《五等分的花嫁》漫画完结!2020年10月第2期TV动画制作组换血!
2020/03/06 日漫
php 页面执行时间计算代码
2008/12/04 PHP
在WordPress的后台中添加顶级菜单和子菜单的函数详解
2016/01/11 PHP
浅谈PHP中关于foreach使用引用变量的坑
2016/11/14 PHP
php7基于递归实现删除空文件夹的方法示例
2017/06/15 PHP
JQuery中extend使用介绍
2014/03/13 Javascript
jQuery实现提交按钮点击后变成正在处理字样并禁止点击的方法
2015/03/24 Javascript
JavaScript动态修改背景颜色的方法
2015/04/16 Javascript
DOM 高级编程
2015/05/06 Javascript
JavaScript获取客户端IP的方法(新方法)
2016/03/11 Javascript
JS实现消息来时让网页标题闪动效果的方法
2016/04/20 Javascript
js常用的继承--组合式继承
2017/03/06 Javascript
vue router demo详解
2017/10/13 Javascript
javascript触发模拟鼠标点击事件
2019/06/26 Javascript
vue.js 子组件无法获取父组件store值的解决方式
2019/11/08 Javascript
vue仿淘宝滑动验证码功能(样式模仿)
2019/12/10 Javascript
javascript中的相等操作符(==与===区别)
2019/12/21 Javascript
使用JS location实现搜索框历史记录功能
2019/12/23 Javascript
Python文件和目录操作详解
2015/02/08 Python
python单例模式实例分析
2015/04/08 Python
关于Tensorflow中的tf.train.batch函数的使用
2018/04/24 Python
Python3使用SMTP发送带附件邮件
2020/06/16 Python
Python 多维List创建的问题小结
2019/01/18 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
2019/06/18 Python
在keras中实现查看其训练loss值
2020/06/16 Python
使用html5制作loading图的示例
2014/04/14 HTML / CSS
瑞典度假品牌:OAS
2019/05/28 全球购物
Oracle里面常用的数据字典有哪些
2014/02/14 面试题
博士毕业生自我鉴定范文
2014/04/13 职场文书
教师年度考核个人总结
2015/02/12 职场文书
2015年街道除四害工作总结
2015/05/15 职场文书
催款函怎么写
2015/06/24 职场文书
青年文明号创建口号大全
2015/12/25 职场文书
PyTorch 如何自动计算梯度
2021/05/23 Python
MySQL Shell import_table数据导入的实现
2021/08/07 MySQL
讲解MySQL增删改操作
2022/05/06 MySQL