2016-10-21 3 views
18

Вчера я обновил Django Rest Framework до 3.5.0, потому что мне нужно красивое создание схемы.Как сгенерировать список сообщений ответа в django rest swagger?

Я использую Django Rest Swagger для документирования моего API, но не знаю, как перечислять все возможные ответные сообщения, которые предоставляет конечная точка API.

Кажется, что есть автоматическое создание сообщения об успешном завершении, соответствующее действию, которое выполняет моя конечная точка. Таким образом, POST-команды генерируют 201 код ответа без описания.

enter image description here

Как бы идти о добавлении всех ответных сообщений, что моя конечная точка предоставляет и дать им некоторые описания?

Я использую

djangorestframework==3.5.0

django-rest-swagger==2.0.7

ответ

16

Ах, наконец, получил его.

Но! Это взломать взломать - и, возможно, drf + drf swagger не поддерживает это; В основном проблема не связана с кодом ФПИ и DRF развязность, скорее 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 - просто для каждой ссылки (например: GET/api/v1/test /) создайте шаблон с пустым описанием.

Конечно, есть возможность преодолеть эту проблему. Но, как я сказал, - это взломать на хак :) Поделюсь пример с вами:

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_generator.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 - есть ли у них планы поддержать ответы?

Во всяком случае, чванство UI: enter image description here

Днем кодирования :)

+5

«? Может быть, вы должны спросить у создателей ФПИ чванство - У них есть планы поддержки ответов» - Верный. Генерация схемы схемы REST еще не * включает в себя любую информацию схемы ответа. 3.6 релиз Django REST framework * может * сделать, хотя это пока не задано. –

+0

Эй, Себастьян, большое спасибо за ваше решение. Поскольку Том заявил, что не будет указано, что правильная схема ответа будет отправлена ​​в 3.6, я буду сильно использовать ваш ответ для реализации схемы пользовательских откликов. – Erika

+1

Определение схемы типа 'list' с' элементами' типа 'object' не показывало список объектов в пользовательском интерфейсе. Вместо этого я получаю только текстовый «список». Он отлично работал, когда я изменил значение 'type' на' array' вместо 'list'. –