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:

Solution1 Solution2

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?

2

There are 2 best solutions below

2
On BEST ANSWER

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

1
On

You can use the decorator:

from rest_framework.decorators import api_view

and then above your function use:

@api_view(['POST'])