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操作MongoDB基础知识
Nov 01 Python
python自定义异常实例详解
Jul 11 Python
matplotlib设置legend图例代码示例
Dec 19 Python
全面了解Nginx, WSGI, Flask之间的关系
Jan 09 Python
30秒轻松实现TensorFlow物体检测
Mar 14 Python
Python中关键字global和nonlocal的区别详解
Sep 03 Python
PyQt 图解Qt Designer工具的使用方法
Aug 06 Python
Django使用Jinja2模板引擎的示例代码
Aug 09 Python
利用python Selenium实现自动登陆京东签到领金币功能
Oct 31 Python
python加载自定义词典实例
Dec 06 Python
Python实现分数序列求和
Feb 25 Python
Python连接Mysql进行增删改查的示例代码
Aug 03 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
总集篇&特番节目先行播出!《SAO Alicization War of Underworld》第2季度TV动画4月25日放送!
2020/03/06 日漫
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
JavaScript中判断函数是new还是()调用的区别说明
2011/04/07 Javascript
jQuery EasyUI API 中文文档 - Documentation 文档
2011/09/29 Javascript
js获取height和width的方法说明
2013/01/06 Javascript
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
使用indexOf等在JavaScript的数组中进行元素查找和替换
2013/09/18 Javascript
showModelDialog弹出文件下载窗口的使用示例
2013/11/19 Javascript
JS常用字符串处理方法应用总结
2014/05/22 Javascript
javascript 动态创建表格
2015/01/08 Javascript
JS实现仿中关村论坛评分后弹出提示效果的方法
2015/02/23 Javascript
Js与Jq 获取页面元素值的方法和差异对比
2015/04/30 Javascript
JS选中checkbox后获取table内一行TD所有数据的方法
2015/07/01 Javascript
javascript经典特效分享 手风琴、轮播图、图片滑动
2016/09/14 Javascript
js实现的xml对象转json功能示例
2016/12/24 Javascript
详解JavaScript常量定义
2017/01/03 Javascript
angular指令笔记ng-options的使用方法
2017/09/18 Javascript
three.js中3D视野的缩放实现代码
2017/11/16 Javascript
vue iview组件表格 render函数的使用方法详解
2018/03/15 Javascript
微信小程序实现城市列表选择
2018/06/05 Javascript
微信小程序实现点击效果
2019/06/21 Javascript
原生js实现html手机端城市列表索引选择城市
2020/06/24 Javascript
python使用paramiko实现远程拷贝文件的方法
2016/04/18 Python
深入学习Python中的装饰器使用
2016/06/20 Python
读取本地json文件,解析json(实例讲解)
2017/12/06 Python
Python使用matplotlib绘制多个图形单独显示的方法示例
2018/03/14 Python
python排序函数sort()与sorted()的区别
2018/09/18 Python
Pandas之Fillna填充缺失数据的方法
2019/06/25 Python
django之对FileField字段的upload_to的设定方法
2019/07/28 Python
Python接口测试get请求过程详解
2020/02/28 Python
美国电视购物:QVC
2017/02/06 全球购物
英国家喻户晓的折扣商场:TK Maxx
2017/05/26 全球购物
应用服务器有那些
2012/01/19 面试题
公司年会晚宴演讲稿
2014/01/06 职场文书
婚礼父母答谢词
2015/01/04 职场文书
单方投资意向书
2015/05/11 职场文书