Documentation is essential when using the REST APIs. It is much easier to use the REST API when code examples are provided. Therefore, I wanted to add show code examples in documentation when building Typless. After some research, we’ve decided to go with ReDoc docs built by drf-yasg. It is quite easy using ReDoc code examples when building static docs for your API. On the other hand, it is not the case when using dynamically built docs in your Django REST framework project.

Path to ReDoc code examples inside docs

Firstly, we’ve searched if ReDoc code examples are supported out of the box in any package. After some digging into docs and source code of drf-yasg package, I’ve found out that I can’t do it easily.

Furthermore, I’ve decided to find I way to do it with drf-yasg. Therefore, I’ve started reading docs of drf-yasg page by page. It seemed like I’ve found something when I come to the Custom schema generation section. Consequently, I’ve decided to override the SwaggerAutoSchema class to include code examples into the docs. After investigating code in the SwaggerAutoSchema class, I’ve realized that self.overrides attribute contains kwargs from @swagger_auto_schema decorator.

Finally, I’ve found a way to add ReDoc code examples to docs. First of all, I needed to override the get_operation method. I did it like this:

from drf_yasg.inspectors import SwaggerAutoSchema

class CustomAutoSchema(SwaggerAutoSchema):

    def get_operation(self, operation_keys=None):
        operation_keys = operation_keys or self.operation_keys

        consumes = self.get_consumes()
        produces = self.get_produces()

        body = self.get_request_body_parameters(consumes)
        query = self.get_query_parameters()
        parameters = body + query
        parameters = filter_none(parameters)
        parameters = self.add_manual_parameters(parameters)

        operation_id = self.get_operation_id(operation_keys)
        summary, description = self.get_summary_and_description()
        security = self.get_security()
        assert security is None or isinstance(security, list), "security must be a list of security requirement objects"
        deprecated = self.is_deprecated()
        tags = self.get_tags(operation_keys)

        responses = self.get_responses()

        return openapi.Operation(
            operation_id=operation_id,
            description=force_real_str(description),
            summary=force_real_str(summary),
            responses=responses,
            parameters=parameters,
            consumes=consumes,
            produces=produces,
            tags=tags,
            security=security,
            deprecated=deprecated,
            **{'x-code-samples': self.overrides.get('code_examples')}
        )

The code is almost the same as original one. There is only tiny detail added.

**{'x-code-samples': self.overrides.get('code_examples')}

I’ve added an x-code-samples argument to call using dictionary unpacking. I did it because is not allowed in variable names. After that, it was easy to add code examples to view methods. Use this schema in your view

class MyViewSet(viewsets.ModelViewSet):
    swagger_schema = CustomAutoSchema

and @swagger_auto_schema decorator before each method in view.

    @swagger_auto_schema(
        code_examples=[
            {
                'lang': 'bash',
                'source': 'curl -H "Authorization: Token YOUR-API-KEY" https://developers.typless.com/api/document-types/'
            },
        ]
    )

As a result, we were able to add code examples to Typless API docs. You could use a similar approach to add other ReDoc vendor extensions. I hope that I helped you.

Happy coding!

Categories: DjangoPython

2 Comments

Pair programming - how we started and what we learned? · April 2, 2020 at 8:15 pm

[…] ReDoc code examples in DRF […]

Asyncio HTTP server in Python - how I did it - Jan Giacomelli · April 10, 2020 at 9:08 am

[…] ReDoc code examples in DRF with drf-yasg […]

Leave a Reply