美文网首页Django
django-rest-framework 自定义swagger

django-rest-framework 自定义swagger

作者: 行如风 | 来源:发表于2017-10-20 11:37 被阅读4020次

    前言

    之前的文章编写了一个返回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/就是为他俩准备的. 因为有时我们需要让接口文档登录之后才能够被看到..

    最后运行项目看到

    swagger0.png

    剩下的问题

    我们的第一个接口没有参数. 向接口文档的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参数.

    最终效果.

    token0.png

    相关文章

      网友评论

        本文标题:django-rest-framework 自定义swagger

        本文链接:https://www.haomeiwen.com/subject/qtamuxtx.html