经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Django » 查看文章
django-rest-framework 自定义swagger过程详解
来源:jb51  时间:2019/7/19 9:10:11  对本文有异议

前言

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

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

环境

  1. workon python35
  2. pip list
  1. chardet (3.0.4)
  2. coreapi (2.3.3)
  3. coreschema (0.0.4)
  4. Django (1.11.6)
  5. django-rest-swagger (2.1.2)
  6. django-simple-serializer (2.0.7)
  7. djangorestframework (3.7.1)
  8. future (0.16.0)
  9. idna (2.6)
  10. itypes (1.1.0)
  11. Jinja2 (2.9.6)
  12. MarkupSafe (1.0)
  13. openapi-codec (1.3.2)
  14. pip (9.0.1)
  15. pytz (2017.2)
  16. requests (2.18.4)
  17. setuptools (36.6.0)
  18. simplejson (3.11.1)
  19. uritemplate (3.0.0)
  20. urllib3 (1.22)
  21. 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

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'rest_framework',
  9. 'rest_framework_swagger',
  10. 'mytest',
  11. ]

我们导入了三个框架

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

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

  1. REST_FRAMEWORK = {
  2. # 下面这一行表示接口文档的访问权限, AllowAny不做权限限制.
  3. 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
  4. # 'PAGE_SIZE': 10,
  5. 'PAGINATE_BY':10,
  6. }
  7.  
  8.  
  9. SWAGGER_SETTINGS = {
  10. # 基础样式
  11. 'SECURITY_DEFINITIONS': {
  12. "basic":{
  13. 'type': 'basic'
  14. }
  15. },
  16. # 如果需要登录才能够查看接口文档, 登录的链接使用restframework自带的.
  17. 'LOGIN_URL': 'rest_framework:login',
  18. 'LOGOUT_URL': 'rest_framework:logout',
  19. # 'DOC_EXPANSION': None,
  20. # 'SHOW_REQUEST_HEADERS':True,
  21. # 'USE_SESSION_AUTH': True,
  22. # 'DOC_EXPANSION': 'list',
  23. # 接口文档中方法列表以首字母升序排列
  24. 'APIS_SORTER': 'alpha',
  25. # 如果支持json提交, 则接口文档中包含json输入框
  26. 'JSON_EDITOR': True,
  27. # 方法列表字母排序
  28. 'OPERATIONS_SORTER': 'alpha',
  29. 'VALIDATOR_URL': None,
  30. }

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

思路:

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

  1. from rest_framework.schemas import get_schema_view

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

接下来编写自己的schema

  1. from rest_framework.permissions import AllowAny
  2. from rest_framework.schemas import SchemaGenerator
  3. from rest_framework.schemas.generators import LinkNode, insert_into
  4. from rest_framework.renderers import *
  5. from rest_framework_swagger import renderers
  6. from rest_framework.response import Response
  7.  
  8. # from rest_framework.schemas import SchemaGenerator
  9. class MySchemaGenerator(SchemaGenerator):
  10.  
  11. def get_links(self, request=None):
  12. # from rest_framework.schemas.generators import LinkNode,
  13. links = LinkNode()
  14.  
  15. paths = []
  16. view_endpoints = []
  17. for path, method, callback in self.endpoints:
  18. view = self.create_view(callback, method, request)
  19. path = self.coerce_path(path, method, view)
  20. paths.append(path)
  21. view_endpoints.append((path, method, view))
  22.  
  23. # Only generate the path prefix for paths that will be included
  24. if not paths:
  25. return None
  26. prefix = self.determine_path_prefix(paths)
  27.  
  28. for path, method, view in view_endpoints:
  29. if not self.has_view_permissions(path, method, view):
  30. continue
  31. link = view.schema.get_link(path, method, base_url=self.url)
  32. # 添加下面这一行方便在views编写过程中自定义参数.
  33. link._fields += self.get_core_fields(view)
  34.  
  35. subpath = path[len(prefix):]
  36. keys = self.get_keys(subpath, method, view)
  37.  
  38. # from rest_framework.schemas.generators import LinkNode, insert_into
  39. insert_into(links, keys, link)
  40.  
  41. return links
  42.  
  43. # 从类中取出我们自定义的参数, 交给swagger 以生成接口文档.
  44. def get_core_fields(self, view):
  45. return getattr(view, 'coreapi_fields', ())
  46.  
  47.  
  48. class SwaggerSchemaView(APIView):
  49. _ignore_model_permissions = True
  50. exclude_from_schema = True
  51.  
  52. # from rest_framework.permissions import AllowAny
  53. permission_classes = [AllowAny]
  54. # from rest_framework_swagger import renderers
  55. # from rest_framework.renderers import *
  56. renderer_classes = [
  57. CoreJSONRenderer,
  58. renderers.OpenAPIRenderer,
  59. renderers.SwaggerUIRenderer
  60. ]
  61.  
  62. def get(self, request):
  63. generator = MySchemaGenerator(title='xxxxx',
  64. description='''xxxxx''')
  65.  
  66. schema = generator.get_schema(request=request)
  67.  
  68. # from rest_framework.response import Response
  69. return Response(schema)

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

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

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

最后一步

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

  1. from django.conf.urls import url, include
  2. from django.contrib import admin
  3. from rest_framework.schemas import get_schema_view
  4. from mytest.views import ReturnJson
  5. import mytest
  6. # 下面是刚才自定义的schema
  7. from mytest.views import SwaggerSchemaView
  8.  
  9. urlpatterns = [
  10. url(r'^admin/', admin.site.urls),
  11. url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
  12. url(r'^docs/', SwaggerSchemaView.as_view(), name='apiDocs'),
  13. url(r'^api/getjson', ReturnJson.as_view()),
  14. ]

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

api-auth/和docs/

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

  1. 'LOGIN_URL': 'rest_framework:login',
  2. 'LOGOUT_URL': 'rest_framework:logout',

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

最后运行项目看到

剩下的问题

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

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

添加以下代码

  1. def DocParam(name="default", location="query",
  2. required=True, description=None, type="string",
  3. *args, **kwargs):
  4. return coreapi.Field(name=name, location=location,
  5. required=required, description=description,
  6. type=type)
  7.  
  8.  
  9. class ReturnJson(APIView):
  10.  
  11. coreapi_fields=(
  12. DocParam("token"),
  13. )
  14.  
  15. def get(self, request, *args, **kwargs):
  16. return JsonResponse("Hello world!!!!!!!!++++++中文测试")

这是所有的import

  1. from django.shortcuts import render
  2. from rest_framework.views import APIView
  3. from dss.Serializer import serializer
  4. from django.http import HttpResponse, HttpRequest
  5. from rest_framework.permissions import AllowAny
  6. from rest_framework.schemas import SchemaGenerator
  7. from rest_framework.schemas.generators import LinkNode, insert_into
  8. from rest_framework.renderers import *
  9. from rest_framework_swagger import renderers
  10. from rest_framework.response import Response
  11. # from rest_framework.schemas import *

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

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

最终效果.

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号