top of page
5.15 Technologies

Swagger For Django: Creating Useable API Documentation

Are you tired of sifting through pages of dull and confusing API documentation? Do you wish there was a more visually appealing and interactive way to understand and utilize API endpoints? If so, then you're in luck!


Introducing Swagger! A powerful tool that allows you to create stunning and intuitive documentation for your Django API. With Swagger, you can create an interactive webpage that not only lists your API endpoints, but also allows users to easily test them and see the results in real-time.


But that's not all. Swagger also provides an easy way to share your API documentation with others. Whether it's with internal team members or external clients. With clear and concise documentation, everyone can understand your API's capabilities and use them effectively. So, let's not waste any more time and start bringing some life to your API documentation with Swagger!


What is Swagger?

Swagger is an extremely powerful and useful user interface to an API. This helps end users understand and test the APIs without needing much prior knowledge of the API itself. The Swagger page that will be discussed during this article will be built on top of our Django Sample Application. The build out for the Swagger page will be in its own branch. This will build on top of the api branch and can be accessed here.


A typical Swagger page will often include all endpoints that are available through the API. In addition to any documentation that is needed to use each endpoint. The documentation for each endpoint will vary depending on if it requires input data or is just a simple GET method. If the API requires authentication, the Swagger page can also include authenticated API requests.


Setting up the Django Swagger Page

There isn’t a ton of setup required to get a Swagger page implemented for your Django API. So, let's just jump right in! The first thing to keep in mind is any Python libraries needed. For the Swagger implementation, the drf-yasg Python library is required. This will ensure the Swagger page can be implemented. The requirements.txt file should now look like the below.

Django~=3.2.16
python-dateutil~=2.8.2
urllib3~=1.26.12
requests~=2.28.1
djangorestframework~=3.14.0
drf-yasg~=1.21.4

After the Python library is installed, you need to ensure the drf_yasg app is added to the INSTALLED_APPS variable in settings.py as shown below.

INSTALLED_APPS = [
    'app',
    'api',
    'rest_framework',
    'personnel',
    'drf_yasg', 
    … TRUNCATED
]

Additionally, the below variable and settings are also added to the settings.py file to configure the Swagger interface.

SWAGGER_SETTINGS = {
    'USE_SESSION_AUTH': False,
    'DEFAULT_FIELD_INSPECTORS': [
        'drf_yasg.inspectors.CamelCaseJSONFilter',
        'drf_yasg.inspectors.InlineSerializerInspector',
        'drf_yasg.inspectors.RelatedFieldInspector',
        'drf_yasg.inspectors.ChoiceFieldInspector',
        'drf_yasg.inspectors.FileFieldInspector',
        'drf_yasg.inspectors.DictFieldInspector',
        'drf_yasg.inspectors.SimpleFieldInspector',
        'drf_yasg.inspectors.StringDefaultFieldInspector',
    ],
    'SECURITY_DEFINITIONS': {
        'Basic': {
            'type': 'basic'
        }
    }
 }

Once the app is added to the INSTALLED_APPS variable and the additional SWAGGER_SETTINGS have been set, the last file that needs to be updated is the urls.py in the “api” app. There are a few imports that are required. A path for the Swagger page and a schema configuration for the Swagger page. The urls.py file for the “api” app should now look like the following:

from django.urls import path
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from . import views

schema_view = get_schema_view(
    openapi.Info(
        title="Django Sample Application API",
        default_version='v1',
        description="Welcome to the Django Sample Application API documentation",
    ),
    public=True,
    permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    path('api/swagger', schema_view.with_ui('swagger', cache_timeout=0),
         name='schema-swagger-ui'),
    path('api/personnel', views.Personnel.as_view(), name='api-personnel'),
    path('api/personnel/<int:_id>', views.PersonnelSingle.as_view(), name='api-personnel-single'),
]

Once all the above changes are made, start the Django server. You should be able to navigate to http://127.0.0.1:8000/api/swagger. If you are running the Django application on a different system, you'll want to replace 127.0.0.1 with that system’s IP address. The Swagger page should look like the following. Though, as you can see, there is not any actual documentation yet for any of the endpoints. We’ll cover how to fix that in the next section.

Formatting and Testing the Swagger Page

At this point, we have a fully functional Swagger page. All endpoints are automatically loaded from our defined API views. Each class that has inherited from the djangorestframework APIView class will automatically be loaded into the Swagger platform. You can easily use this syntax to automatically include or exclude endpoints from the Swagger page.


Now, as far as documentation is concerned, it is quite simple. There are three main configurations that make up the documentation for an endpoint. The first of these is the serializers. The serializers will use a model, but you can manually configure them as well to set the input fields required for an endpoint. You can configure the serializer to exclude certain fields if needed. The serializers used for our setup are outlined below.

class PersonnelPost(serializers.ModelSerializer):
    class Meta:
        model = PersonnelModel
        exclude = []

class PersonnelPatchSingle(PersonnelPost):
    def get_fields(self):
        new_fields = OrderedDict()

        for name, field in super().get_fields().items():
            if name != 'id':
                field.required = False
                new_fields[name] = field
            else:
                new_fields[name] = field
        return new_fields

class PersonnelPatch(PersonnelPatchSingle):
    id = serializers.IntegerField()

The PersonnelPost serializer uses the PersonnelModel to determine the fields that are going to be needed when adding new entries to the database. All these fields will be required. The PersonnelPatchSingle serializer inherits from the PersonnelPost serializer and iterates through each of the fields and marks them as optional, except for the id field. Lastly, the PersonnelPatch serializer inherits from the PersonnelPatchSingle serializer and adds the required id field.


Now that we understand how the serializers work, we can configure the endpoints themselves. For this demonstration, we will be looking at the POST method for the personnel endpoint as seen below. We add a @swagger_auto_schema decorator to outline what the response and request should look like. As well as update the preview text for the endpoint in the UI using the operation_id parameter. Afterwards, we added a docstring to the method that will give the endpoint a description in the UI. The first line of the docstring will show up on the Swagger page before expanding the item. Whereas the rest of the docstring will be visible after expanding the item.

@swagger_auto_schema(
    request_body=PersonnelPost(many=True), operation_id='Create Personnel', responses={201: PersonnelPost(many=True)}

)
def post(self, request):
    """
    Create one, or many, Personnel

    This method will create as many Personnel as are passed into the payload. The payload needs to be either a \
    list of dictionaries or a single dictionary. The response will be in JSON format with the results of the \
    creations under the 'data' key
    """

After configuring all our endpoints, the Swagger page should look like the following.

Expanding the POST method for the personnel endpoint will show the description that we created earlier. As well as the data required for creating a new instance in the database.

To quickly test the API, you can click the “Try it out” button, which should give you a prompt as seen below.

Once the data is updated and you click execute, if you scroll down, you should see an output like the following. Your output will show the data you input instead of what was input above.

Conclusion

As you can see, creating a Swagger page for your Django API can be a game-changer for your documentation needs. With Swagger's interactive and visually appealing interface, you can create clear and concise documentation. This makes it easy for both developers and non-developers to understand your API's capabilities.


By following the steps outlined in this blog, you can easily install and configure Swagger for your Django application and begin documenting your API endpoints with annotations. With Swagger, you can not only provide detailed information about each endpoint, but also allow users to test them and see the results in real-time. The benefits of using Swagger don't stop there. With its built-in sharing features, you can easily share your API documentation with others, allowing for increased collaboration and improved communication. So why settle for dull and confusing API documentation when you can create something truly remarkable with Swagger.


Thank you for taking the time to review this article and feel free to contact us if your project needs more advanced capabilities.


Comments


bottom of page