Development
-
August 22, 2023

Automating Django REST APIs documentation made easy with DRF Spectacular - Part 1

Documenting a REST API is of paramount importance for several reasons. First and foremost, it serves as a clear and comprehensive guide for developers and users, providing them with essential information on how to interact with the API and its endpoints. A well-documented API eliminates confusion, reduces learning curves, and accelerates the development process. Moreover, documentation enhances collaboration among team members, ensuring that everyone is on the same page and can work seamlessly together. It also facilitates integration with other systems, making it easier for external developers to utilize the API effectively.

At times, developers may find themselves reluctant to invest time and effort in documenting their REST APIs, especially when under tight deadlines or overwhelmed with other tasks. Fortunately, there's a powerful solution to this problem when working on Django REST APIs, and it’s a library called DRF Spectacular.

This blog post is divided into two parts. In the first one, I will guide you through the process of setting up and configuring the mentioned tool. Additionally, I will demonstrate how the library automatically generates documentation using an example project, and provide some helpful tips. The second part of the post will delve further into the example project, exploring its various features, and showcasing additional tools offered by the library for more specific customization.

Swagger and DRF Spectacular

Swagger, also known as OpenAPI 3 and OpenAPI Specification (OAS), is a standard to document APIs. It is easy to use, it’s language-agnostic, promotes good practices, and helps people to quickly understand the features.

DRF Spectacular is a library to generate, maintain, and easily customize Django REST APIs documentation. It’s used to generate Swagger schemas. With this library, schemas will be generated automatically, and you will be able to see them in the browser. Besides, you will be able to define environments and test them while viewing the documentation.

Install and setup

The DRF library has a very clear and concise section of installation and setup so I won’t specify the step by step instructions. The only thing I would like to add is that if by security reasons, you want that only admin users from Django to use the API documentation, you can add this to the SPECTACULAR_SETTINGS dictionary:

CODE: https://gist.github.com/brunomichetti/5f8e5ba50ee9f882d9bd2b43b9d493a2.js?file=serve_permissions.py

This way, any person that wants to access the docs, will need first to login to the Django Admin page. Otherwise the person will see a page with 403 Forbidden.

After a correct installation and setup, you should have this added in your urls file:

CODE: https://gist.github.com/brunomichetti/af2315849754eea4e49db543cae7e948.js?file=urlpatterns.py

With this configuration, if you start the server and access in your browser to api/schema you will be redirected to download a yaml file that contains the documentation automatically generated by the library. This is how the file looks:

Also, you can open in the browser a Swagger UI if you go to api/schema/swagger-ui/ that has this aspect:

And finally, if you access to api/schema/redoc/ you will see the Redoc mode of your documentation:

Personally, I like the Swagger UI view, so from now on, the future examples in this blog will be shown in that mode. The important thing of this section is that after a correct setup and installation, you already have a documentation of your API automatically generated.

Example project

As mentioned above, the DRF Spectacular library has a “Read the docs” page, but you can encounter problems when you try to make specific customizations to your automatically generated documentation.

Here I present a small example project to demonstrate how powerful this tool is, and also to explain easily all the customization options available.

This project has users, and each user can have a leader user, that means there is a 1 to N relationship from the model user to itself. Here is a list of features:

  • Create users.
  • List and filter users. The users can be filtered by username.
  • List the users inside a leadership tree of a given user.
  • Set a user as the leader of another user.
  • List the users that are leaders.
  • Get calculated metrics of the users.
  • Delete a user.

For this, I have created a CustomUser model, that inherits from the Django User model. The important fields in this reality are:

  • username.
  • first_name.
  • last_name.
  • password.

Let’s see the definition of the model in the users app:

CODE: https://gist.github.com/brunomichetti/4a9b4dc65f6b1b171725658d4e5d9ce0.js?file=custom_user.py

The important mentioned fields are inherited from the User class.

Automatically generated documentation

Let’s see the views, functions and serializers of this project, to understand all the work that the library does for us generating the documentation. After the installation and setup, I only need to code the features, and the documentation will be created for me. Amazing, right?

Creation

I want to ask for a unique username, mandatory first name and last name, and password and password confirmation.

The endpoint receives this data and returns id, first and last names, and username. This is the serializer:

CODE: https://gist.github.com/brunomichetti/c113b4c78a3331788f01214ba62d5138.js?file=user_create_serializer.py

List

In the listing endpoint, I want to show only the id and username of each user. This is the serializer:

CODE: https://gist.github.com/brunomichetti/7a594f0470bc30ff94d7aaea71e2878e.js?file=user_list_serializer.py

User detail

When getting a user detail, I want the id, username, first and last names, leader id and the led users. Of each led user I only want the id and username. This is the serializer:

CODE: https://gist.github.com/brunomichetti/c752c3e9a0167252e51a3190b01b0da3.js?file=user_detail_serializer.py

The view

This is the ViewSet defined as the view of the user's app. I use the mixins CreateModelMixin, ListModelMixin and RetrieveModelMixin of Django REST framework to already have respectively the endpoints of creation, listing, and getting a user detail. In the get_serializer_class function I defined which serializer to use on each endpoint. I also modified the perform_create function to properly set the user’s password with the Django function called set_password . Finally, I use the amazing django-filter library to filter the listed users by username, creating the UserFilter. The ViewSet has the route api/users/. This is the UsersViewSet:

CODE: https://gist.github.com/brunomichetti/99dc14ec68e2102b1b2136de7bcee475.js?file=user_viewset.py

The automatically generated documentation

I started the server, and went to api/schema/swagger-ui/ in my browser, to show you what the DRF Spectacular library has automatically generated:

Clicking on the list users endpoint:

As you can see, there is the username query parameter to filter by username. Also the response status code and the fields of each user in the list.

Clicking on the creation endpoint:

You can see that the password and password_confirm aren’t returned in the response because I don’t want that and I set those fields as write_only. In an analogous way, I set the id as read_only, so it’s returned only in the response.

Clicking on the user detail endpoint:

This returns more user data. The leader_id and list of led users were added.

This is great! All this documentation was generated by DRF Spectacular. I have only installed and configured the library and created the endpoints. I can even test the endpoints by clicking on the Try it out button.

These are the functions of Django and Django REST framework that are used by the library by default to generate the documentation:

  • get_serializer_class: Returns the class that should be used for the serializer. Defaults to returning the serializer_class attribute.
  • get_serializer: Used to retrieve the appropriate serializer class for a given request and view.

Docstrings to add more information about the endpoints

If I want to add comments or a description for the endpoint, or explain it even more, I can do it very quickly by adding docstrings to the corresponding functions. In this example, since I am using the mixins CreateModelMixin, ListModelMixin and RetrieveModelMixin, I would have to add docstrings to the create, list and retrieve function. In this case I need to override the functions returning the parent one and adding the desired docstrings. Let’s see an example with the create function in the UserViewSet:

CODE: https://gist.github.com/brunomichetti/99c3d1ddc71548088064f88863216e3b.js?file=create_user_function.py

And now in the docs this appears:

You can also add descriptions in the docstrings of custom actions.

Another way of adding descriptions is using extend_schema, I'll explain it in the next blog post.

Summary

In this blog post, we delved into the world of documenting a Django REST API using the DRF Spectacular library. One of the main highlights is the library's incredible ability to automatically generate comprehensive documentation, significantly reducing the amount of manual effort required. To demonstrate its capabilities, I've presented an example project and included some helpful configuration tips.

In the upcoming second part, we'll take a closer look at advanced customizations and powerful tools offered by the DRF Spectacular library. By delving deeper into these aspects, I aim to empower readers to make the most out of this invaluable toolset.

I sincerely hope you enjoyed the blog post and encourage you to share your ideas and feedback. Stay tuned for the next part, where we continue our exploration of DRF Spectacular's possibilities.