I am trying to integrate django-rest-swagger==2.1.1
with my existing project that uses djangorestframework==3.5.3
.
The project has some Class based views and some Function based views. After integrating swagger, It displays input boxes for POST requests of "Class Based views"(which have serializers obviously), but does not show for "function based views". The question has been asked several times, I have tried following solutions:
and few others too, but did not work for my case. Is there any possible way to do that for 'function based views' or I ll have to convert them to class based views?
YAML docstring parser is deprecated in REST Swagger>=2.0
What I did is to override the SchemaGenerator class to parse the view's docstring by my own conventions.
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.schemas import SchemaGenerator
from rest_framework.views import APIView
from rest_framework_swagger import renderers
import yaml
import coreapi
import urlparse
class SchemaGenerator(SchemaGenerator):
def get_link(self, path, method, view):
"""Custom the coreapi using the func.__doc__ .
if __doc__ of the function exist, use the __doc__ building the coreapi. else use the default serializer.
__doc__ in yaml format, eg:
description: the desc of this api.
parameters:
- name: mobile
desc: the mobile number
type: string
required: true
location: form
- name: promotion
desc: the activity id
type: int
required: true
location: form
"""
fields = self.get_path_fields(path, method, view)
yaml_doc = None
if view and view.__doc__:
try:
yaml_doc = yaml.load(view.__doc__)
except:
yaml_doc = None
if yaml_doc and type(yaml_doc) != str:
_method_desc = yaml_doc.get('description', '')
params = yaml_doc.get('parameters', [])
for i in params:
_name = i.get('name')
_desc = i.get('description')
_required = i.get('required', False)
_type = i.get('type', 'string')
_location = i.get('location', 'form')
field = coreapi.Field(
name=_name,
location=_location,
required=_required,
description=_desc,
type=_type
)
fields.append(field)
else:
_method_desc = view.__doc__ if view and view.__doc__ else ''
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
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,
description=_method_desc
)
def get_swagger_view(title=None, url=None, patterns=None, urlconf=None):
"""
Returns schema view which renders Swagger/OpenAPI.
"""
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 = SchemaGenerator(
title=title,
url=url,
patterns=patterns,
urlconf=urlconf
)
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()
Create this module anywhere in project structure. Import get_swagger_view
from this module in project/urls.py
. And, then remove the get_swagger_view
method from the django_rest_swagger
module.
Ref: Comment by daimon99 in REST Swagger Issues
Update: As from django-rest-framework
version 3.7, there are breaking changes due to which above code won't work, the solution would be Comment by GuillaumeCisco