Functional overview

OpenAPI specification overview

This library generates OpenAPI 2.0 documents. The authoritative specification for this document’s structure will always be the official documentation over at swagger.io and the OpenAPI 2.0 specification page.

Because the above specifications are a bit heavy and convoluted, here is a general overview of how the specification is structured, starting from the root Swagger object.

  • Swagger object
    • info, schemes, securityDefinitions and other informative attributes
    • paths: Paths object
      A list of all the paths in the API in the form of a mapping
      • {path}: PathItem - each PathItem has multiple operations keyed by method
        • {http_method}: Operation
          Each operation is thus uniquely identified by its (path, http_method) combination, e.g. GET /articles/, POST /articles/, etc.
        • parameters: [Parameter] - and a list of path parameters
    • definitions: named Models
      A list of all the named models in the API in the form of a mapping
  • Operation contains the following information about each operation:
    • parameters: [Parameter]
      A list of all the query, header and form parameters accepted by the operation.
      • there can also be at most one body parameter whose structure is represented by a Schema or a reference to one (SchemaRef)
    • responses: Responses
      A list of all the possible responses the operation is expected to return. Each response can optionally have a Schema which describes the structure of its body.
      • {status_code}: Response - mapping of status code to response definition
    • operationId - should be unique across all operations
    • tags - used to group operations in the listing

It is interesting to note the main differences between Parameter and Schema objects:

Schema Parameter
Can nest other Schemas Cannot nest other Parameters
Can only nest a Schema if the parameter is in: body
Cannot describe file uploads
- file is not permitted as a value for type
Can describe file uploads via type = file,
but only as part of a form Operation [1]
Can be used in Responses Cannot be used in Responses
Cannot be used in form Operations [1] Can be used in form Operations [1]
Can only describe request or response bodies Can describe query, form, header or path parameters
[1](1, 2, 3)

a form Operation is an Operation that consumes multipart/form-data or application/x-www-form-urlencoded content

  • a form Operation cannot have body parameters
  • a non-form operation cannot have form parameters

Default behavior

This section describes where information is sourced from when using the default generation process.

  • Paths are generated by exploring the patterns registered in your default urlconf, or the patterns and urlconf you specified when constructing OpenAPISchemaGenerator; only views inheriting from Django Rest Framework’s APIView are looked at, all other views are ignored

  • path Parameters are generated by looking in the URL pattern for any template parameters; attempts are made to guess their type from the views queryset and lookup_field, if applicable. You can override path parameters via manual_parameters in @swagger_auto_schema.

  • query Parameters - i.e. parameters specified in the URL as /path/?query1=value&query2=value - are generated from your view’s filter_backends and paginator, if any are declared. Additional parameters can be specified via the query_serializer and manual_parameters arguments of @swagger_auto_schema

  • The request body is only generated for the HTTP POST, PUT and PATCH methods, and is sourced from the view’s serializer_class. You can also override the request body using the request_body argument of @swagger_auto_schema.

    • if the view represents a form request (that is, all its parsers are of the multipart/form-data or application/x-www-form-urlencoded media types), the request body will be output as form Parameters
    • if it is not a form request, the request body will be output as a single body Parameter wrapped around a Schema
  • header Parameters are supported by the OpenAPI specification but are never generated by this library; you can still add them using manual_parameters.

  • Responses are generated as follows:

    • if responses is provided to @swagger_auto_schema and contains at least one success status code (i.e. any 2xx status code), no automatic response is generated and the given response is used as described in the @swagger_auto_schema documentation

    • otherwise, an attempt is made to generate a default response:

      • the success status code is assumed to be 204 for DELETE requests, 201 for POST requests, and 200 for all other request methods
      • if the view has a request body, the same Serializer or Schema as in the request body is used in generating the Response schema; this is inline with the default GenericAPIView and GenericViewSet behavior
      • if the view has no request body, its serializer_class is used to generate the Response schema
      • if the view is a list view (as defined by is_list_view()), the response schema is wrapped in an array
      • if the view is also paginated, the response schema is then wrapped in the appropriate paging response structure
      • the description of the response is left blank
  • Response headers are supported by the OpenAPI specification but not currently supported by this library; you can still add them manually by providing an appropriately structured dictionary to the headers property of a Response object

  • descriptions for Operations, Parameters and Schemas are picked up from docstrings and help_text attributes in the same manner as the default DRF SchemaGenerator

  • The base URL for the API consists of three values - the host, schemes and basePath attributes

  • The host name and scheme are determined, in descending order of priority:

    For example, an url of https://www.example.com:8080/some/path will populate the host and schemes attributes with www.example.com:8080 and ['https'], respectively. The path component will be ignored.

  • The base path is determined as the concatenation of two variables:

    1. the SCRIPT_NAME wsgi environment variable; this is set, for example, when serving the site from a sub-path using web server url rewriting

      Tip

      The Django FORCE_SCRIPT_NAME setting can be used to override the SCRIPT_NAME or set it when it’s missing from the environment.

    2. the longest common path prefix of all the urls in your API - see determine_path_prefix()

  • When using API versioning with NamespaceVersioning or URLPathVersioning, versioned endpoints that do not match the version used to access the SchemaView will be excluded from the endpoint list - for example, /api/v1.0/endpoint will be shown when viewing /api/v1.0/swagger/, while /api/v2.0/endpoint will not

    Other versioning schemes are not presently supported.

A note on limitations

When schema generation is requested, available endpoints are inspected by enumeration all the routes registered in Django’s urlconf. Each registered view is then artificially instantiated for introspection, and it is this step that brings some limitations to what can be done:

  • the request the view sees will always be the request made against the schema view endpoint - e.g. GET /swagger.yaml
  • path parameters will not be filled

This means that you could get surprizing results if your get_serializer or get_serializer_class methods depend on the incoming request, call get_object or in general depend on any stateful logic. You can prevent this in a few ways:

  • provide a fixed serializer for request and response body introspection using @swagger_auto_schema, to prevent get_serializer from being called on the view

  • exclude your endpoint from introspection

  • use the swagger_fake_view marker to detect requests generated by drf-yasg:

    def get_serializer_class(self):
       if getattr(self, 'swagger_fake_view', False):
          return TodoTreeSerializer
    
       raise NotImplementedError("must not call this")