schemas

Schema

A machine-readable [schema] describes what resources are available via the API, what their URLs are, how they are represented and what operations they support.

— Heroku, [JSON Schema for the Heroku Platform API][cite]

API schemas are a useful tool that allow for a range of use cases, includinggenerating reference documentation, or driving dynamic client libraries thatcan interact with your API.

Django REST Framework provides support for automatic generation ofOpenAPI schemas.

Generating an OpenAPI Schema

Install pyyaml

You'll need to install pyyaml, so that you can render your generated schemainto the commonly used YAML-based OpenAPI format.

  1. pip install pyyaml

Generating a static schema with the generateschema management command

If your schema is static, you can use the generateschema management command:

  1. ./manage.py generateschema > openapi-schema.yml

Once you've generated a schema in this way you can annotate it with anyadditional information that cannot be automatically inferred by the schemagenerator.

You might want to check your API schema into version control and update itwith each new release, or serve the API schema from your site's static media.

Generating a dynamic schema with SchemaView

If you require a dynamic schema, because foreign key choices depend on databasevalues, for example, you can route a SchemaView that will generate and serveyour schema on demand.

To route a SchemaView, use the get_schema_view() helper.

In urls.py:

  1. from rest_framework.schemas import get_schema_view
  2. urlpatterns = [
  3. # ...
  4. # Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
  5. # * `title` and `description` parameters are passed to `SchemaGenerator`.
  6. # * Provide view name for use with `reverse()`.
  7. path('openapi', get_schema_view(
  8. title="Your Project",
  9. description="API for all things …",
  10. version="1.0.0"
  11. ), name='openapi-schema'),
  12. # ...
  13. ]

get_schema_view()

The get_schema_view() helper takes the following keyword arguments:

  • title: May be used to provide a descriptive title for the schema definition.
  • description: Longer descriptive text.
  • version: The version of the API.
  • url: May be used to pass a canonical base URL for the schema.
  1. schema_view = get_schema_view(
  2. title='Server Monitoring API',
  3. url='https://www.example.org/api/'
  4. )
  • urlconf: A string representing the import path to the URL conf that you want to generate an API schema for. This defaults to the value of Django's ROOT_URLCONF setting.
  1. schema_view = get_schema_view(
  2. title='Server Monitoring API',
  3. url='https://www.example.org/api/',
  4. urlconf='myproject.urls'
  5. )
  • patterns: List of url patterns to limit the schema introspection to. If you only want the myproject.api urls to be exposed in the schema:
  1. schema_url_patterns = [
  2. url(r'^api/', include('myproject.api.urls')),
  3. ]
  4. schema_view = get_schema_view(
  5. title='Server Monitoring API',
  6. url='https://www.example.org/api/',
  7. patterns=schema_url_patterns,
  8. )
  • generator_class: May be used to specify a SchemaGenerator subclass to be passed to the SchemaView.

  • authentication_classes: May be used to specify the list of authentication classes that will apply to the schema endpoint. Defaults to settings.DEFAULT_AUTHENTICATION_CLASSES

  • permission_classes: May be used to specify the list of permission classes that will apply to the schema endpoint. Defaults to settings.DEFAULT_PERMISSION_CLASSES.
  • renderer_classes: May be used to pass the set of renderer classes that can be used to render the API root endpoint.

Customizing Schema Generation

You may customize schema generation at the level of the schema as a whole, oron a per-view basis.

Schema Level Customization

In order to customize the top-level schema sublassrest_framework.schemas.openapi.SchemaGenerator and provide it as an argumentto the generateschema command or get_schema_view() helper function.

SchemaGenerator

A class that walks a list of routed URL patterns, requests the schema for eachview and collates the resulting OpenAPI schema.

Typically you'll instantiate SchemaGenerator with a title argument, like so:

  1. generator = SchemaGenerator(title='Stock Prices API')

Arguments:

  • title required: The name of the API.
  • description: Longer descriptive text.
  • version: The version of the API. Defaults to 0.1.0.
  • url: The root URL of the API schema. This option is not required unless the schema is included under path prefix.
  • patterns: A list of URLs to inspect when generating the schema. Defaults to the project's URL conf.
  • urlconf: A URL conf module name to use when generating the schema. Defaults to settings.ROOT_URLCONF.
get_schema(self, request)

Returns a dictionary that represents the OpenAPI schema:

  1. generator = SchemaGenerator(title='Stock Prices API')
  2. schema = generator.get_schema()

The request argument is optional, and may be used if you want to applyper-user permissions to the resulting schema generation.

This is a good point to override if you want to customize the generateddictionary, for example to add customspecification extensions.

Per-View Customization

By default, view introspection is performed by an AutoSchema instanceaccessible via the schema attribute on APIView. This provides theappropriate Open API operation object for the view,request method and path:

  1. auto_schema = view.schema
  2. operation = auto_schema.get_operation(...)

In compiling the schema, SchemaGenerator calls view.schema.get_operation()for each view, allowed method, and path.


Note: For basic APIView subclasses, default introspection is essentiallylimited to the URL kwarg path parameters. For GenericAPIViewsubclasses, which includes all the provided class based views, AutoSchema willattempt to introspect serializer, pagination and filter fields, as well asprovide richer path field descriptions. (The key hooks here are the relevantGenericAPIView attributes and methods: get_serializer, pagination_class,filter_backends and so on.)


In order to customize the operation generation, you should provide an AutoSchema subclass, overriding get_operation() as you need:

  1. from rest_framework.views import APIView
  2. from rest_framework.schemas.openapi import AutoSchema
  3. class CustomSchema(AutoSchema):
  4. def get_operation(...):
  5. # Implement custom introspection here (or in other sub-methods)
  6. class CustomView(APIView):
  7. """APIView subclass with custom schema introspection."""
  8. schema = CustomSchema()

This provides complete control over view introspection.

You may disable schema generation for a view by setting schema to None:

  1. class CustomView(APIView):
  2. ...
  3. schema = None # Will not appear in schema

This also applies to extra actions for ViewSets:

  1. class CustomViewSet(viewsets.ModelViewSet):
  2. @action(detail=True, schema=None)
  3. def extra_action(self, request, pk=None):
  4. ...

If you wish to provide a base AutoSchema subclass to be used throughout yourproject you may adjust settings.DEFAULT_SCHEMA_CLASS appropriately.