Problem
Swagger / OpenAPI can be regarded as the de-facto standard for API documentation and sandbox for experimenting with and learning a new API. Adding this to a REST API Django project is important. The process for this integration can have some hiccups based on documentation debt and deprecated packages and these hiccups cost time. Wouldn’t it be great to have some clear step by step instructions that can be ran through smoothly and quickly (4 mins or less)
Assumptions
- A Django rest api project is already set up.
- User only needs to add the swagger / OpenAPI integration.
- Using Django 3+.
Cautionary Tale
First let me describe the journey through a pitfall that many may fall into when trying to rapidly get this up and running. The first thing you might do is do a quick google, find a guide for the integration using django-rest-swagger package and start churning through steps, before hitting some road blocks and having to change course. This may look like your experience.
You use pip to install django-rest-swagger package
pip install django-rest-swagger
Update settings.py file in main Django project to load django-rest-swagger app.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'rest_framework_swagger', # <-- Here
'base',
'user_api',
'obj_api',
'jac_api',
'ui',
]
Update urls.py file in main Django project to first load the get_swagger_view utility function and then add path to route to Swagger UI view.
from django.contrib import admin
from django.urls import path, include
from rest_framework_swagger.views import get_swagger_view # <-- Here
schema_view = get_swagger_view(title='Jaseci API')
urlpatterns = [
path('docs/', schema_view), # <-- Here
path('admin/', admin.site.urls),
path('user/', include('user_api.urls')),
path('', include('jac_api.urls')),
path('', include('obj_api.urls')),
path('ui/', include('ui.urls')),
path('ui/', include('django.contrib.auth.urls')),
]
This is where the first hiccup rears it’s head. If you try to load the docs page at this point you may get the following error.

You get an AttributeError at /docs/ 'AutoSchema' object has no attribute 'get_link'.
To solve simply add 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' to the REST_FRAMEWORK parameters.
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':
'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100,
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' # <-- Here
}
You try to reload and run into the second Hiccup.

The issue here is that staticfiles has been deprecated since Django 2 and completely removed for Django 3. The problem is this is not clear from a wealth of how-tos on integrating swagger and DRF on the interwebs. And though it appears there’s an effort to update django-rest-swagger, the community appears to have moved on to drf-yasg, not as clean a name but endorsed by the official django-rest-framework project.

Solution
So lets go ahead and quickly integrate drf-yasg.
Use pip to install drf-yasg package
pip install drf-yasg
Update settings.py file in main Django project to load drf_yasg app.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'drf_yasg', # <-- Here
'base',
'user_api',
'obj_api',
'jac_api',
'ui',
]
Update urls.py file in main Django project to first load the schema_view and paths you’d like.
from django.contrib import admin
from django.urls import path, re_path, include
# drf_yasg code starts here
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Jaseci API",
default_version='v1',
description="Welcome to the world of Jaseci",
terms_of_service="https://www.jaseci.org",
contact=openapi.Contact(email="jason@jaseci.org"),
license=openapi.License(name="Awesome IP"),
),
public=True,
permission_classes=(permissions.AllowAny,),
)
# ends here
urlpatterns = [
re_path(r'^doc(?P<format>\.json|\.yaml)$',
schema_view.without_ui(cache_timeout=0), name='schema-json'), #<-- Here
path('doc/', schema_view.with_ui('swagger', cache_timeout=0),
name='schema-swagger-ui'), #<-- Here
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0),
name='schema-redoc'), #<-- Here
path('admin/', admin.site.urls),
path('user/', include('user_api.urls')),
path('', include('jac_api.urls')),
path('', include('obj_api.urls')),
path('ui/', include('ui.urls')),
path('ui/', include('django.contrib.auth.urls')),
]
Four new paths are created here including
/spec.json(json spec of API doc)/spec.yaml(yaml spec of API doc)/doc(Our nice pretty Swagger UI view of API doc)/redoc(A pretty Redoc view of API doc)
Usage
Now we load /doc in our browser and Viola!

Redoc also looks nice!

Limitations
Hiccups validated to present themselves when using following package versions.
Django>=3.0.3,<3.1.0 djangorestframework>=3.11.0,<3.12.0 django-rest-swagger>=2.2.0,<2.3.0

Leave a Reply
Your email is safe with us.