如何在 Django REST Swagger 中生成响应消息列表?

Posted

技术标签:

【中文标题】如何在 Django REST Swagger 中生成响应消息列表?【英文标题】:How to generate list of response messages in Django REST Swagger? 【发布时间】:2017-03-03 16:36:39 【问题描述】:

我昨天已将 Django REST Framework 升级到 3.5.0,因为我需要很好的模式生成。

我正在使用 Django REST Swagger 来记录我的 API,但不知道如何列出 API 端点提供的所有可能的响应消息。

似乎自动生成了与我的端点正在执行的操作相对应的成功消息。

所以 POST 动作生成 201 响应代码,没有任何描述。

我将如何添加我的端点提供的所有响应消息并给它们一些描述?

我正在使用

djangorestframework==3.5.0

django-rest-swagger==2.0.7

【问题讨论】:

【参考方案1】:

啊,终于明白了。

但是!这是 hack on hack - 可能 drf + drf swagger 不支持这一点;基本上问题不在于drf和drf swagger代码,而是openapi编解码,看自己:

def _get_responses(link):
    """
    Returns minimally acceptable responses object based
    on action / method type.
    """
    template = 'description': ''
    if link.action.lower() == 'post':
        return '201': template
    if link.action.lower() == 'delete':
        return '204': template
    return '200': template

上面的代码可以在:openapi_codec/encode.py - github 这与 drf 或 drf swagger 没有任何联系 - 只是为每个链接(例如:GET /api/v1/test/)创建一个带有空描述的模板。

当然有可能克服这个问题。但正如我所说 - 这是 hack on hack :) 我将与您分享一个示例:

docs_swagger.views.py

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 docs_swagger.schema_generator import CustomSchemaGenerator


def get_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 = CustomSchemaGenerator(title=title, url=url)  # this is altered line
            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()

我在 CustomSchemaGenerator 中的操作如下:

docs_swagger.schema_g​​enerator.py

import urlparse
import coreapi
from rest_framework.schemas import SchemaGenerator

from openapi_codec import encode


def _custom_get_responses(link):
    detail = False
    if 'id' in link.url:
        detail = True
    return link._responses_docs.get(
        '_'.format(link.action, 'list' if not detail else 'detail'),
        link._responses_docs
    )


# Very nasty; Monkey patching;
encode._get_responses = _custom_get_responses


class CustomSchemaGenerator(SchemaGenerator):

    def get_link(self, path, method, view):
        """
        Return a `coreapi.Link` instance for the given endpoint.
        """
        fields = self.get_path_fields(path, method, view)
        fields += self.get_serializer_fields(path, method, view)
        fields += self.get_pagination_fields(path, method, view)
        fields += self.get_filter_fields(path, method, view)

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

        description = self.get_description(path, method, view)

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

        # CUSTOM
        data_link = coreapi.Link(
            url=urlparse.urljoin(self.url, path),
            action=method.lower(),
            encoding=encoding,
            fields=fields,
            description=description
        )

        data_link._responses_docs = self.get_response_docs(path, method, view)

        return data_link

    def get_response_docs(self, path, method, view):
        return view.responses_docs if hasattr(view, 'responses_docs') else '200': 
            'description': 'No response docs definition found.'
        

最后:

my_view.py

class TestViewSet(viewsets.ModelViewSet):
    queryset = Test.objects.all()
    serializer_class = TestSerializer

    responses_docs = 
        'get_list': 
            '200': 
                'description': 'Return the list of the Test objects.',
                'schema': 
                    'type': 'array',
                    'items': 
                        'type': 'object',
                        'properties': 
                            'id': 
                                'type': 'integer'
                            
                        
                    
                
            ,
            '404': 
                'description': 'Not found',
                'schema': 
                    'type': 'object',
                    'properties': 
                        'message': 
                            'type': 'string'
                        
                    
                ,
                'example': 
                    'message': 'Not found.'
                
            
        ,
        'get_detail': 
            '200': 
                'description': 'Return single Test object.',
                'schema': 
                    'type': 'object',
                    'properties': 
                        'id': 
                            'type': 'integer'
                        
                    
                
            ,
            '404': 
                'description': 'Not found.',
                'schema': 
                    'type': 'object',
                    'properties': 
                        'message': 
                            'type': 'string'
                        
                    
                ,
                'example': 
                    'message': 'Not found.'
                
            
        
    

我认为这更像是一种乐趣,而不是真正的解决方案。在目前的状态下,真正的解决方案可能是不可能实现的。也许你应该问问 drf swagger 的创建者——他们有计划支持响应吗?

无论如何,招摇的用户界面:

编码愉快:)

【讨论】:

“也许你应该问问 drf swagger 的创建者 - 他们有计划支持响应吗?” - 正确的。 REST 框架的架构生成尚未包含任何响应架构信息。 Django REST framework 的 3.6 版本可能会这样做,虽然这还不是给定的。 嗨塞巴斯蒂安,非常感谢您的解决方案。正如 Tom 所说,在 3.6 中不会提供适当的响应模式,我将大量使用您的答案来实现自定义响应模式。 items 类型object 定义list 类型的架构没有在UI 中显示对象列表。相反,我只得到文本“列表”。当我将 type 值更改为 array 而不是 list 时,它确实工作正常。 @opalczynski 感谢您发布解决方案。但是我在做同样的事情时遇到了错误。 “链接”对象没有属性“responses_docs”。我使用的 drf 版本是 3.7.7。有什么需要改的吗 @opalczynski docs_swagger.views.py - 这个文件应该放在哪里?

以上是关于如何在 Django REST Swagger 中生成响应消息列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django REST Swagger 中生成响应消息列表?

django-rest-swagger 是不是不适用于模型序列化器?

django-rest-swagger对API接口注释

从 Django REST Swagger 中排除 URL

Django Rest Swagger生成api文档

Django Rest framework Swagger生成api文档