Skip to content

Django REST OpenAPI Generation and Import to APIM Guide

Although Django REST Framework (DRF) enables you to build APIs, it does not provide a standard OpenAPI exporter required by Azure API Management (APIM) for correct route management. This guide explains how to generate an OpenAPI specification for your DRF application using the haskoning_django_utils package, along with the required drf_spectacular package. These utilities include extra features to support OpenAPI generation and export, specifically designed for APIM.

TIP

If you handle authentication in your Django app, and want to use JWT tokens issued by Haskoning Azure AD, check the Django JWT Authentication

1. Install Required Packages with Poetry

The haskoning_django_utils package includes schema generation from version 1.0.7 and requires drf_spectacular version 0.28.0 or higher.

bash
# Install the artifacts-keyring module
poetry self add artifacts-keyring

# Add the haskoning-py feed to your project
poetry source add --priority=supplemental haskoning-py https://pkgs.dev.azure.com/corporateroot/_packaging/haskoning-py/pypi/simple/

poetry add haskoning_django_utils drf_spectacular

# Or specify versions
poetry add drf_spectacular@^0.28.0 haskoning_django_utils@^1.0.7

# haskoning-django-azure-auth-jwt@2.0.12 has an error during schema generation. Upgrade to 2.0.16 or higher to avoid this error.
poetry add haskoning-django-azure-auth-jwt@^2.0.16

After installing, you may need to run poetry lock --regenerate to update your poetry.lock file.

2. Modify your Django settings

Add the following to your INSTALLED_APPS in settings.py or base.py:

python
import os
from haskoning_django_utils.schema.import_settings import get_spectacular_settings
# BASE_DIR is usually already defined
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

INSTALLED_APPS = [
    ...
    "haskoning_django_utils",
    "drf_spectacular",
]
REST_FRAMEWORK = {
    ...
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}

SPECTACULAR_SETTINGS = get_spectacular_settings(
    os.path.join(os.path.dirname(BASE_DIR), "pyproject.toml")
)

INFO

get_spectacular_settings(pyproject_path) reads metadata from pyproject.toml, supporting both legacy [tool.poetry] (pre PEP 621) and modern [project] (PEP 621). Migration to PEP 621 is recommended.
It normalizes author entries: Poetry list form ["Jane Doe <jane@example.com>"] and PEP 621 table form { name = "...", email = "..." }. Only the first author becomes the OpenAPI contact (spec limit). This is handy for maintaining consistent metadata across your project.

3. Update urls.py

Import the schema generator and configure your documentation endpoints:

text
from haskoning_django_utils.schema.schema_generate import SchemaGenerator
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView

# In your urls.py
urlpatterns = [
    # ... your other urls ...
    # Custom openapi.json view (requires authentication by default)
    path("openapi.json", SchemaGenerator.get_custom_openapi_json_view(), name="openapi_custom-json"),
]

Troubleshooting tips: If you encounter errors when accessing /docs/ or /openapi.json, try disabling paths to identify the cause. With this setup, the /docs/, /api/schema/, and /openapi.json endpoints require authentication. Ensure that each view has the correct serializer class defined; otherwise, schema generation may fail.

TIP

If needed, you can also allow access to the Swagger UI and schema view for local testing purposes only by adding the following paths, but be cautious as these routes have no authentication by default:

python
# Include to show the Swagger UI of drf-spectacular (no authentication)
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
path("docs/", SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),

4. Update Your Pipeline

This tutorial assumes you are using pipeline_template to publish your app, and you have followed the previous add-api guide.

Add the following job to your pipeline to generate and export the OpenAPI specification, then import it into Azure API Management using the provided pipeline template (apim). For API configuration details, refer to the equation Terraform file here.

yaml
resources:
  repositories:
    - repository: templates
      type: git
      name: Haskoning-Software-Development/pipeline_templates

jobs:
  - template: 'python/build_web_image_publish_django_container_app_task_apim.yml@templates'
    parameters:
      dockerRegistryServiceConnection: $(dockerRegistryServiceConnection)
      containerAppRegistry: $(containerAppRegistry)
      imageRepository: $(imageRepository)
      containerAppEnvironmentName: $(containerAppEnvironmentName)
      resourceGroupName: $(resourceGroupName)
      azureResourceManagerServiceConnection: $(azureResourceManagerServiceConnection)
      apiManagementServiceName: $(apiManagementServiceName)
      apiServiceID: $(apiServiceID)

For detailed pipeline setup, or if your Django project has different routes that cannot be exposed normally, see the Pipeline Setup Guide.

INFO

For many Django projects, exporting the OpenAPI schema requires running the app (settings, URLs, installed apps) in a Docker environment with real dependencies. We could avoid this by modifying our repositories (e.g., mocking external services, using SQLite or an in‑memory DB, and ensuring serializers/viewsets import cleanly without a full runtime), but that would require too much extra effort, so we use the Docker approach.

5. Test Your Setup

After setup, your API documentation will be available at /docs/, with metadata (title, version, description, contact) automatically extracted from your pyproject.toml.

bash
# if not using Docker
python manage.py migrate
python manage.py export_openapi_schema --output openapi.json

# if using Docker Compose
docker compose run --rm web sh -c "python manage.py migrate && python manage.py export_openapi_schema --output openapi.json"

By default, this exports to openapi_schema.json in your current directory, using the SPECTACULAR_SETTINGS defined earlier.

INFO

The exported schema is in OpenAPI 3.0.1 format, which is compatible with Azure API Management. The output includes /docs/, /openapi.json, and the wildcard /* for the OPTIONS method, which supports CORS preflight requests required by many Vue.js frontend applications.