Skip to main content

Sane and flexible OpenAPI 3 schema generation for Django REST framework

Project description

build-status-image codecov pypi-version docs

Sane and flexible OpenAPI 3 schema generation for Django REST framework.

This project has 3 goals:
  1. Extract as much schema information from DRF as possible.

  2. Provide flexibility to make the schema usable in the real world (not only toy examples).

  3. Generate a schema that works well with the most popular client generators.

The code is a heavily modified fork of the DRF OpenAPI generator, which is/was lacking all of the below listed features.

Features
  • abstraction of serializers into components (better support for openapi-generator)
    • recursive components (e.g. nested PersonSerializer->PersonSerializer->…)

    • components are named after Serializers (i.e. the main interface of your API)

  • @extend_schema decorator for customization of APIView, Viewsets, function-based views, and @action
    • additional manual query parameters

    • request/response serializer override

    • response status code override

    • polymorphic responses (manual by providing serializer list or rest_polymorphic)

    • and more customization options

  • easy to use hooks for extending the spectacular AutoSchema

  • authentication methods in schema (default DRF methods included, easily extendable)

  • MethodSerializerField() type via type hinting or @extend_schema_field

  • schema tags for operations plus override option (very useful in Swagger UI)

  • support for django-polymorphic / django-rest-polymorphic (automatic polymorphic responses for PolymorphicSerializers)

  • description extraction from doc strings

  • sane fallbacks where there are no serializers available (free-form objects)

  • operation_id naming based on endpoint path instead of model name (preventing operation_id duplication)

Incomplete features (in progress):
  • optional separate component versions for PATCH serializers (no required fields)

  • optional input/output serializer component split

License

Provided by T. Franzel, Cashlink Technologies GmbH. Licensed under 3-Clause BSD.

Requirements

  • Python >= 3.6

  • Django (2.2, 3.0)

  • Django REST Framework (3.10, 3.11)

Installation

Install using pip

$ pip install drf-spectacular

then add drf-spectacular to installed apps in settings.py

INSTALLED_APPS = [
    # ALL YOUR APPS
    'drf_spectacular',
]

and finally register our spectacular AutoSchema with DRF

REST_FRAMEWORK = {
    # YOUR SETTINGS
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
    # OR this for usage with rest_polymorphic/django-polymorphic
    # 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.contrib.rest_polymorphic.PolymorphicAutoSchema',
}

Take it for a spin

drf-spectacular is KISS. It only generates a valid OpenAPI 3 specification for you and nothing else. You can easily view your schema with the excellent Swagger UI or any other compliant UI or tool:

$ ./manage.py spectacular --file schema.yml
$ docker run -p 80:8080 -e SWAGGER_JSON=/schema.yml -v ${PWD}/schema.yml:/schema.yml swaggerapi/swagger-ui

Usage

drf-spectacular works pretty well out of the box. The toy examples do not cover your cases? No problem, you can heavily customize how your schema will be rendered.

Customization by using @extend_schema

Most customization cases should be covered by the extend_schema decorator. We usually get pretty far with specifying OpenApiParameter and splitting request/response serializers, but the sky is the limit.

from drf_spectacular.utils import extend_schema, OpenApiParameter
from drf_spectacular.types import OpenApiTypes

class AlbumViewset(viewset.ModelViewset)
    serializer_class = AlbumSerializer

    @extend_schema(
        request=AlbumCreationSerializer
        responses={201: AlbumSerializer},
    )
    def create(self, request):
        # your non-standard behaviour
        return super().create(request)

    @extend_schema(
        # extra parameters added to the schema
        parameters=[
            OpenApiParameter(name='artist', description='Filter by artist', required=False, type=str),
            OpenApiParameter(
                name='release',
                type=OpenApiTypes.DATE,
                location=OpenApiParameter.QUERY,
                description='Filter by release date',
            ),
        ],
        # override default docstring extraction
        description='More descriptive text',
        # provide Authentication class that deviates from the views default
        auth=None,
        # change the auto-generated operation name
        operation_id=None,
        # or even completely override what AutoSchema would generate. Provide raw Open API spec as Dict.
        operation=None,
    )
    def list(self, request):
        # your non-standard behaviour
        return super().list(request)

    @extend_schema(
        request=AlbumLikeSerializer
        responses={204: None},
    )
    @action(detail=True, methods=['post'])
    def set_password(self, request, pk=None):
        # your action behaviour

Customization by overriding AutoSchema

Still not satisifed? You want more! We still got you covered. We prepared some convenient hooks for things that are probably up to taste. If you are careful, you can change pretty much anything.

Don’t forget to register your custom AutoSchema in the DEFAULT_SCHEMA_CLASS.

from drf_spectacular.openapi import AutoSchema

class CustomAutoSchema(AutoSchema):
    def get_operation_id(self, path, method):
        return 'YOUR-ID'.replace('-', '_')

Extras

got endpoints that yield list of differing objects? Enter PolymorphicProxySerializer

@extend_schema(
    responses=PolymorphicProxySerializer(
        component_name='MetaPerson',
        serializers=[SerializerA, SerializerB],
        resource_type_field_name='type',
    )
)
@api_view()
def poly_list(request):
    return Response(list_of_multiple_object_types)

Testing

Install testing requirements.

$ pip install -r requirements.txt

Run with runtests.

$ ./runtests.py

You can also use the excellent tox testing tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:

$ tox

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-spectacular-0.8.8.tar.gz (26.1 kB view details)

Uploaded Source

Built Distribution

drf_spectacular-0.8.8-py2.py3-none-any.whl (85.4 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file drf-spectacular-0.8.8.tar.gz.

File metadata

  • Download URL: drf-spectacular-0.8.8.tar.gz
  • Upload date:
  • Size: 26.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.0.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.5

File hashes

Hashes for drf-spectacular-0.8.8.tar.gz
Algorithm Hash digest
SHA256 412aa75420ae7a74b59b551612aac58ea4fe664528c86251f2ae70827490a9d0
MD5 29584d6782b70de0cd39a3e4aa79caa4
BLAKE2b-256 d29311dac7b9bd7bf0c5d065e1df3b724d39d07181b6183689431dbbb229ba9c

See more details on using hashes here.

Provenance

File details

Details for the file drf_spectacular-0.8.8-py2.py3-none-any.whl.

File metadata

  • Download URL: drf_spectacular-0.8.8-py2.py3-none-any.whl
  • Upload date:
  • Size: 85.4 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.0.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.5

File hashes

Hashes for drf_spectacular-0.8.8-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 c0741afc222806a857e82a3f3bd41b4ecd80006a8dcf6a4df39d994f33c92ff0
MD5 2aa0ccbeed754bff6b802ace67993f48
BLAKE2b-256 013eb7bfa04a78bce71b25d223f5833c63950517cbb63e43bb2c5e2bc8f25735

See more details on using hashes here.

Provenance

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