Django休息框架Api文档Swagger 2.0

时间:2016-11-24 19:20:21

标签: django rest django-rest-framework swagger

我很难配置Swagger UI。以下是非常简洁的文档:https://django-rest-swagger.readthedocs.io/en/latest/

不推荐使用YAML文档字符串。有人知道如何在python代码中配置Swagger UI(查询参数等)吗?

如果出于某种奇怪的原因是不可能的。是否有任何可行的替代方案,或者对我来说最好是手工编写api文档?

1 个答案:

答案 0 :(得分:4)

好的,找到了。这不是理想的解决方案 - 但需要前端(网络和移动)开发人员 - 并且它可以完成这项工作。

基本上最新的DRF和Swagger使用rest_framework.schemas import SchemaGenerator来提供Swagger的文档。

所以我需要对它进行一点延伸:

# -*- coding: utf-8 -*-
import urlparse

import coreapi
from rest_framework.schemas import SchemaGenerator


class ParamsSchemaGenerator(SchemaGenerator):

    def get_link(self, path, method, callback, view):
        """
        Return a `coreapi.Link` instance for the given endpoint.
        """
        fields = self.get_path_fields(path, method, callback, view)
        fields += self.get_serializer_fields(path, method, callback, view)
        fields += self.get_pagination_fields(path, method, callback, view)
        fields += self.get_filter_fields(path, method, callback, view)
        fields += self.get_docs_fields(path, method, callback, view)  # this is the extended line;

        if fields and any([field.location in ('form', 'body') for field in fields]):
            encoding = self.get_encoding(path, method, callback, view)
        else:
            encoding = None

        if self.url and path.startswith('/'):
            path = path[1:]

        return coreapi.Link(
            url=urlparse.urljoin(self.url, path),
            action=method.lower(),
            encoding=encoding,
            fields=fields
        )

    # and this is fully custom additional docs method;
    def get_docs_fields(self, path, method, callback, view):
        fields = []
        if hasattr(view, 'docs_fields'):
            for field in view.docs_fields:
                field = coreapi.Field(
                    name=field.get('name'),
                    location=field.get('query'),
                    required=field.get('required'),
                    type=field.get('type'),
                    description=field.get('description')
                )
                fields.append(field)

        return fields

然后我需要定义一个函数,它将使用上面定义的生成器返回模式:

# -*- coding: utf-8 -*-
# monkey patching FTW!

from rest_framework import exceptions
from rest_framework.permissions import AllowAny
from rest_framework.renderers import CoreJSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_swagger import renderers

from kolomnie.core.schema.generator import ParamsSchemaGenerator


def get_params_swagger_view(title=None, url=None):
    """
    Returns schema view which renders Swagger/OpenAPI.

    (Replace with DRF get_schema_view shortcut in 3.5)
    """
    class SwaggerSchemaView(APIView):
        _ignore_model_permissions = True
        exclude_from_schema = True
        permission_classes = [AllowAny]
        renderer_classes = [
            CoreJSONRenderer,
            renderers.OpenAPIRenderer,
            renderers.SwaggerUIRenderer
        ]

        def get(self, request):
            generator = ParamsSchemaGenerator(title=title, url=url)
            schema = generator.get_schema(request=request)

            if not schema:
                raise exceptions.ValidationError(
                    'The schema generator did not return a schema Document'
                )

            return Response(schema)

    return SwaggerSchemaView.as_view()

这就是我把它放在网址中的方式:

if settings.DEBUG:
    api_views = get_params_swagger_view(title='Some API')

现在更加神奇了,我为视图定义了一个mixin来存储文档字段:

# -*- coding: utf-8 -*-


class DocsMixin(object):
    """
    This mixin can be used to document the query parameters in GET
    if there's no other way to do it. Please refer to the: ParamsSchemaGenerator.get_links
    for more information;
    """
    docs_fields = []

这就是我使用它的方式:

class BaseSearchResultsView(generics.GenericAPIView, SearchDocs):
    ....

SearchDocs就是这样:

class SearchDocs(DocsMixin):
    """
    Documents the get query in search;
    """
    docs_fields = [
        {
            'name': 'q',
            'location': 'query',
            'required': False,
            'type': 'string',
            'description': 'The base query for the search;',
        },
    ...

发现我不需要mixin :)只是在视图上定义了docs_fields。

可能这不会满足您的所有需求 - 但认为这是一个好的开始:)

快乐的编码!