Custom schema generation¶
If the default spec generation does not quite match what you were hoping to achieve, drf-yasg
provides some
custom behavior hooks by default.
Swagger spec 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.
Beause 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.
Operation
contains the following information about each operation:operationId
- should be unique across all operationstags
- 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 Response s |
Cannot be used in Response s |
Cannot be used in form Operation s [1] |
Can be used in form Operation s [1] |
[1] | (1, 2, 3) a form Operation is an
|
The @swagger_auto_schema
decorator¶
You can use the @swagger_auto_schema
decorator on view functions to override
some properties of the generated Operation
. For example, in a ViewSet
,
@swagger_auto_schema(operation_description="partial_update description override", responses={404: 'slug not found'})
def partial_update(self, request, *args, **kwargs):
"""partial_update method docstring"""
...
will override the description of the PATCH /article/{id}/
operation, and document a 404 response with no body and
the given description.
Where you can use the @swagger_auto_schema
decorator depends on the type of your view:
for function based
@api_view
s, because the same view can handle multiple methods, and thus represent multiple operations, you have to add the decorator multiple times if you want to override different operations:test_param = openapi.Parameter('test', openapi.IN_QUERY, description="test manual param", type=openapi.TYPE_BOOLEAN) user_response = openapi.Response('response description', UserSerializer) @swagger_auto_schema(method='get', manual_parameters=[test_param], responses={200: user_response}) @swagger_auto_schema(methods=['put', 'post'], request_body=UserSerializer) @api_view(['GET', 'PUT', 'POST']) def user_detail(request, pk): ...
for class based
APIView
,GenericAPIView
and non-ViewSet
derivatives, you have to decorate the respective method of each operation:class UserList(APIView): @swagger_auto_schema(responses={200: UserSerializer(many=True)}) def get(self, request): ... @swagger_auto_schema(operation_description="description") def post(self, request): ...
for
ViewSet
,GenericViewSet
,ModelViewSet
, because each viewset corresponds to multiple paths, you have to decorate the action methods, i.e.list
,create
,retrieve
, etc.
Additionally,@list_route
s or@detail_route
s defined on the viewset, like function based api views, can respond to multiple HTTP methods and thus have multiple operations that must be decorated separately:class ArticleViewSet(viewsets.ModelViewSet): @swagger_auto_schema(operation_description='GET /articles/today/') @list_route(methods=['get']) def today(self, request): ... @swagger_auto_schema(method='get', operation_description="GET /articles/{id}/image/") @swagger_auto_schema(method='post', operation_description="POST /articles/{id}/image/") @detail_route(methods=['get', 'post'], parser_classes=(MultiPartParser,)) def image(self, request, id=None): ... @swagger_auto_schema(operation_description="PUT /articles/{id}/") def update(self, request, *args, **kwargs): ... @swagger_auto_schema(operation_description="PATCH /articles/{id}/") def partial_update(self, request, *args, **kwargs): ...
Subclassing and extending¶
For more advanced control you can subclass SwaggerAutoSchema
- see the documentation page for a list of
methods you can override.
You can put your custom subclass to use by setting it on a view method using the
@swagger_auto_schema
decorator described above.
If you need to control things at a higher level than Operation
objects (e.g. overall document structure,
vendor extensions in metadata) you can also subclass OpenAPISchemaGenerator
- again, see the documentation
page for a list of its methods.
This custom generator can be put to use by setting it as the generator_class
of a SchemaView
using
get_schema_view()
.