Swagger with Django REST Framework

Swagger with Django REST Framework
Swagger with Django REST Framework

In this article, we will use Swagger to generate documentation for our API. We will use a third-party package that will simply auto-generate Swagger documentation for implemented endpoints with DRF.

First, install the example repository from Github which is a very simple blog app with a few models that will help us to see the Swagger documentation.  

GitHub - PylotStuff/swagger-drf: Swagger with DRF to generate API documentation.
Swagger with DRF to generate API documentation. Contribute to PylotStuff/swagger-drf development by creating an account on GitHub.

Once installation is completed, open the requirements.txt file to see installed dependencies:

django
djangorestframework
drf_yasg

We're using a Python package named drf_yasg which automatically creates documentation for implemented endpoints.

It's also required to include drf_yasg into INSTALLED_APPS configuration:

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'drf_yasg', # <- here
    'post',
]

Next, we should initialize the SchemaView class that holds default renderers and generators. Then, point it to a specific path which will be the actual Swagger documentation.

urls.py

from django.contrib import admin
from django.urls import path, include

from drf_yasg import openapi
from drf_yasg.views import get_schema_view as swagger_get_schema_view


schema_view = swagger_get_schema_view(
    openapi.Info(
        title="Posts API",
        default_version='1.0.0',
        description="API documentation of App",
    ),
    public=True,
)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', 
        include([
            path('post/', include(('post.api.urls', 'post'), namespace='posts')),
            path('swagger/schema/', schema_view.with_ui('swagger', cache_timeout=0), name="swagger-schema"),
        ])
    ),
]

get_schema_view accepts multiple arguments that can be used while initialization.

info is the first param of get_schema_view which defaults to openapi.Info. It's accepting the following params:

  • title – Title of API (required)
  • default_version– API version string (not to be confused with Swagger spec version, Required)
  • description – API description (markdown supported)
  • terms_of_service – API terms of service (should be a URL)
  • contact (Contact) – contact object
  • license (License) – license object

With the configurations above, you'll be able to see API docs by navigating localhost:8000/api/v1/swagger/schema.

Some DRF methods are built-in where you're not implementing them directly. In this case, you can customize the generation of a method instead of overriding the internal logic by decorating the classes using a combination of swagger_auto_schema and  method_decorator:

@method_decorator(name='get', decorator=swagger_auto_schema(
    manual_parameters=[
        openapi.Parameter(
            'post_slug', openapi.IN_QUERY,
            description=("A unique string value identifying requested post"),
            type=openapi.TYPE_STRING,
            enum=[ps.value for ps in PostStatus],
            required=True
        ),
    ]
))
class PingView(APIView):

    def get(self, *args, **kwargs):
        return Response({'ping': 'pong'}, status=status.HTTP_200_OK)

swagger_auto_schema decorator allows us to customize View functions but since we need the class itself then method_decorator will do the work.

These were the main parts of designing the API documentation with DRF. For more details, please check the official documentation.

Support 🌏

If you feel like you unlocked new skills, please share with your friends and subscribe to the youtube channel to not miss any valuable information.