Skip to main content

Manage OpenApi documentation with DRF

Project description

DRF OpenApi 3

OpenApi 3 utility for Django REST Framework

Enhances DRF AutoSchema and SchemaGenerator to help generating a better OpenApi 3 documentation.

Supports servers, deprecated and summary in schema generation, now you mark them as deprecated and display the summary besides the description. If you want your ApiView to display custom content in the documentation, you can add it by writing comments to the view/view method in YAML format. Fixed request body and responses for views that handle multiple objects, such as bulk insert, bulk update and bulk delete. Now they are displayed as array.

Installation

  1. Install the package using pip install drf_openapi3
  2. Add drf_openapi3.apps.OpenApi3Config to Django INSTALLED_APPS

Configuration

  1. OpenApi documentation View

Extend drf_openapi3.views.OpenApiTemplateView. You can define a title and template name, otherwise default values will be used.

from django.contrib.auth.mixins import LoginRequiredMixin
from drf_openapi3.views import OpenApiTemplateView


class MyOpenApiTemplateView(LoginRequiredMixin, OpenApiTemplateView):
    title = 'My OpenAPI'
    template_name = 'path/to/mytemplate.html'
  1. Add schema to urlpatterns using drf_openapi3.AdvancedSchemaGenerator as generator class
from django.contrib.auth.decorators import login_required
from django.urls import path
from drf_openapi3.schemas.advanced import AdvancedSchemaGenerator
from rest_framework.schemas import get_schema_view


urlpatterns = [
    # Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
    #   * `title` and `description` parameters are passed to `SchemaGenerator`.
    #   * Provide view name for use with `reverse()`.
    path('my-schema/', login_required(
        get_schema_view(
            title='My API',
            description='My API description',
            version='1.0.0',
            generator_class=AdvancedSchemaGenerator,
            public=True,
        ),
        login_url='/accounts/login/',
    ), name='my_schema_name'),
    # ...
    # ...
]
  1. Start writing your ApiViews.
from rest_framework.generics import ListAPIView


class MyAPIListView(ListAPIView):
    allowed_methods = ['get']

    def get(self, request, *args, **kwargs):
        return super(MyAPIListView, self).list(request, *args, **kwargs)

How to use

Let's see step by step what you can do.

Define multiple servers

Useful for instance if you provide a test sandbox together with a production server. In Django settings you can define url and description in API_SERVERS:

API_SERVERS = [
    {
        "url": "https://test.example.com/",
        "description": "Sandbox server (uses test data)",
    },
    {
        "url": "https://example.com/",
        "description": "Production server (uses live data)",
    },
]

If you don't define anything, Django BASE_URL will be used to build your server block. So if you are developing in local environment, the server url will be http://localhost:8000. If it's production environment, the server url will be https://example.com. Keep in mind that defining multiple servers in API_SERVERS will allow users to switch server urls in the dropdown on the documentation before testing your endpoints.

Apply tags to your ApiView

If you want to tag your view, just pass tags to your view schema. Default is "api". You can decide your own, it can come in handy to add the endpoint version:

from drf_openapi3.schemas.advanced import AdvancedAutoSchema
from rest_framework.generics import ListAPIView


class MyAPIListView(ListAPIView):
    # ...
    # ...
    allowed_methods = ['get']
    schema = AdvancedAutoSchema(
        tags=["v0"],
        component_name="My",
        operation_id_base="MyAPI",
        handles_many_objects=True
    )

    def get(self, request, *args, **kwargs):
        return super(MyAPIListView, self).list(request, *args, **kwargs)

Apply deprecated to your old ApiView

If you want to mark your view as deprecated, just add the attribute deprecated = True to your view schema:

from drf_openapi3.schemas.advanced import AdvancedAutoSchema
from rest_framework.generics import ListAPIView


class MyAPIListView(ListAPIView):
    # ...
    # ...
    allowed_methods = ['get']
    schema = AdvancedAutoSchema(
        tags=["v0"],
        component_name="My",
        operation_id_base="MyAPI",
        handles_many_objects=True,
        deprecated=True
    )

    def get(self, request, *args, **kwargs):
        return super(MyAPIListView, self).list(request, *args, **kwargs)

Views that handle multiple objects with methods besides GET

When you write a view that performs bulk create, update or delete operations you face some issues on the documentation:

the responses field schema types are object, but they should be array.

By adding handles_many_objects=True attribute to your view schema, you tell the schema that responses must be array.

from drf_openapi3.schemas.advanced import AdvancedAutoSchema
from rest_framework.generics import ListCreateAPIView
from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_200_OK



class MyListPostView(ListCreateAPIView):
    # ...
    # ...
    allowed_methods = ['get', 'post']
    schema = AdvancedAutoSchema(
        tags=["v0"],
        component_name="My",
        operation_id_base="MyAPI",
        handles_many_objects=True,
    )

    def post(self, request, *args, **kwargs) -> Response:
        serialized = self.get_serializer(data=request.data, many=True)
        if serialized.is_valid():
            serialized.save()
            return Response(serialized.data, status=HTTP_200_OK)
        return Response(serialized.errors, status=HTTP_400_BAD_REQUEST)

Display custom content in the documentation

DRF AutoSchema already reads your view/view method Docstring:

if you want to display the endpoint description in your documentation, you can write some text in the view/view method Docstring.

That wasn't enough for me though.

Let's start with the simplest one, the same one that's already implemented from DRF AutoSchema that it has been kept to have backwards compatibility:

we add a plain description in the view Docstring. If we do it on both view and method view, only method view Docstring will be taken into account:

from drf_openapi3.schemas.advanced import AdvancedAutoSchema
from rest_framework.generics import ListCreateAPIView
from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_200_OK


class MyListPostView(ListCreateAPIView):
    """
    This is my endpoint description and it will be reported 
    for each allowed method.
    """
    # ...
    # ...
    allowed_methods = ['get', 'post']
    schema = AdvancedAutoSchema(
        tags=["v0"],
        component_name="My",
        operation_id_base="MyListPost",
        handles_many_objects=True,
    )   

    def post(self, request, *args, **kwargs) -> Response:
        """
        ... and that's my method description
        Since both the descriptions are defined you'll see only this one.
        You won't see "This is my endpoint description", 
        unless you delete the text here above.
        """
        serialized = self.get_serializer(data=request.data, many=True)
        if serialized.is_valid():
            serialized.save()
            return Response(serialized.data, status=HTTP_200_OK)
        return Response(serialized.errors, status=HTTP_400_BAD_REQUEST)

If you want to manage custom changes to your schema, just add them to the Docstring in YAML format. You'll notice that it'll be easier for you to read your code too.

By default DRF AutoSchema displays only status code 200 as example response. Since 400, 401, 403, 404 status codes return a JSON {"detail": <error detail>}, in Django settings you can define STATIC_ERROR_CODES = True to display more responses in your documentation. If you have to perform further changes on responses in your view, you can put them in YAML view/view method Docstring.

If you want to limit the allowed response codes that you're going to see on the documentation, just list the allowed status codes in your view (allowed_status_codes); this is useful when you had enabled STATIC_ERROR_CODES and you want to prevent some responses to be displayed.

We're getting creative here, let's add a complete example:

from drf_openapi3.schemas.advanced import AdvancedAutoSchema
from rest_framework.generics import ListAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView


class MyCommentedView(ListAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView):
    """
        get:
            summary: Summary for get method
            description: Description for get method
        post:
            summary: Summary for post method
            description: Description for post method
            400:
                description: Invalid object, that's a custom description of 400 response code for post method
        put:
            summary: Summary for put method
            description: Description for put method
        delete:
            summary: Summary for delete method
            description: Description for delete method
            200:
                description: Corsa objects deleted, that's a custom description of 200 response code for delete method
                schema:
                    type: array
                    items:
                        properties:
                            field:
                                type: boolean
                                description: Deleted flag, here we define a different schema for bulk delete
    """
    allowed_methods = ("GET", "POST", "PUT", "DELETE")
    allowed_status_codes = (200, 400, 401, 403)

    schema = AdvancedAutoSchema(
        tags=["v0"],
        component_name="MyCommented",
        operation_id_base="MyCommentedWriteDelete",
        handles_many_objects=True,
    )

# ...
# ...

If you've overridden the view methods already (.get(), .post(), .put(), .delete()) you can write there your comments. Please be advised that if you do so you must not use the notation method: properties:

from rest_framework.generics import ListAPIView, DestroyAPIView
from rest_framework.response import Response
from rest_framework.status import HTTP_200_OK


class MyCommentedView(ListAPIView, DestroyAPIView):

    def delete(self, request, *args, **kwargs) -> Response:
        """
        summary: Summary for delete method
        description: Description for delete method
        200:
            description: Corsa objects deleted, that's a custom description of 200 response code for delete method
            schema:
                type: array
                items:
                    properties:
                        field:
                            type: boolean
                            description: Deleted flag, here we define a different schema for bulk delete
        """
        output = []
        for data in request.data:
            # ...
            # ...
            pass
        return Response(output, status=HTTP_200_OK)

Last but not least: do you want to set a default sort for your endpoints? Just pass index=n to AdvancedAutoSchema:

from drf_openapi3.schemas.advanced import AdvancedAutoSchema
from rest_framework.generics import ListAPIView, ListCreateAPIView


class MyAPIListView(ListAPIView):
    # ...
    # ...
    allowed_methods = ['get']
    schema = AdvancedAutoSchema(
        index=0,
        tags=["v0"],
        component_name="My",
        operation_id_base="MyAPI",
        handles_many_objects=True,
        deprecated=True
    )


class MyListPostView(ListCreateAPIView):
    """
    This is my endpoint description and it will be reported 
    for each allowed method.
    """
    # ...
    # ...
    allowed_methods = ['get', 'post']
    schema = AdvancedAutoSchema(
        index=1,
        tags=["v0"],
        component_name="My",
        operation_id_base="MyListPost",
        handles_many_objects=True,
    )   

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_openapi3-0.1.24.tar.gz (36.1 kB view details)

Uploaded Source

Built Distribution

drf_openapi3-0.1.24-py2.py3-none-any.whl (36.0 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file drf_openapi3-0.1.24.tar.gz.

File metadata

  • Download URL: drf_openapi3-0.1.24.tar.gz
  • Upload date:
  • Size: 36.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.54.1 CPython/3.9.0

File hashes

Hashes for drf_openapi3-0.1.24.tar.gz
Algorithm Hash digest
SHA256 72a53b3abe11412708c9b9a4dd3ecaa8482b77a43d489430a6904da5fb5822cd
MD5 5df5a0278349f768810755edffc8f09e
BLAKE2b-256 fe9dfe5d690b7cf7852ef0bf468a32256ebb2245d2152a646842f38482d8682c

See more details on using hashes here.

File details

Details for the file drf_openapi3-0.1.24-py2.py3-none-any.whl.

File metadata

  • Download URL: drf_openapi3-0.1.24-py2.py3-none-any.whl
  • Upload date:
  • Size: 36.0 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.1 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.54.1 CPython/3.9.0

File hashes

Hashes for drf_openapi3-0.1.24-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 21bff63cca69f6152b5117bfe62ff62bc92175240c5f40fc6f645cc3863174c3
MD5 57f993db1d45aa7de2df173fb83ec826
BLAKE2b-256 336a7d255e832dc4ed5a4059aed7bf88e8b58ef408a074f52fefa0769e4ac5e2

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page