Skip to main content

OpenAPI (v3) schema generation via Pydantic models using Django REST Framework.

Project description

drf-pydantic-openapi

Generate OpenAPI schema with DRF code using Pydantic models. Supports referencing other services' components.

Installation

pip install drf-pydantic-openapi

Add to INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "rest_framework",
    "drf_pydantic_openapi",
]

Configuration

Add settings to your project's settings.py:

DRF_PYDANTIC_OPENAPI = {
    "TITLE": "My API",
    "DESCRIPTION": "API Documentation",
    "API_VERSION": "1.0",
    "OPENAPI_VERSION": "3.1.0",
    "SERVERS": ["https://api.example.com"],
    "INCLUDE_EMPTY_ENDPOINTS": False,
    "REF_SOURCES": {
        "service_B": "http://localhost:8000/openapi/schema.json",
        "service_C": "http://localhost:8001/openapi/schema.json",
    },
    "SECURITY_DEFINITIONS": {
        "BearerAuth": {
            "type": "http",
            "scheme": "bearer",
        }
    },
}

URL Setup

from django.urls import path, re_path
from drf_pydantic_openapi.views import (
    get_schema_view,
    DrfPydanticRedocView,
    DrfPydanticSwaggerView,
    DrfPydanticRapidocView,
)

urlpatterns = [
    re_path(
        "openapi/schema.json",
        get_schema_view(
            api_version="v1",  # optional: filter by API version
            tag_path_regex="/api/v1/",  # optional: regex for extracting tags
            permission_classes=[],  # optional: DRF permission classes
            authentication_classes=[],  # optional: DRF authentication classes
        ).as_view(),
        name="dpo_schema",
    ),
    re_path("openapi/redoc", DrfPydanticRedocView.as_view(), name="redoc"),
    re_path("openapi/swagger", DrfPydanticSwaggerView.as_view(), name="swagger"),
    re_path("openapi/rapidoc", DrfPydanticRapidocView.as_view(), name="rapidoc"),
]

Or use the default URLs:

from django.urls import path, include

urlpatterns = [
    path("openapi/", include("drf_pydantic_openapi.urls")),
]

Available endpoints with default URLs:

  • /openapi/schema.json - OpenAPI schema
  • /openapi/docs - ReDoc documentation

Using the @docs Decorator

Parameters:

  • body: Request body model
  • errors: List of error models
  • query: Query parameters model
  • path: Path parameters model
  • response: Response model (overrides return type annotation)
from pydantic import BaseModel, Field
from rest_framework.views import APIView
from drf_pydantic_openapi.utils import docs
from drf_pydantic_openapi.errors import BadRequestError, NotFoundError

class PathParams(BaseModel):
    book_id: str = Field(description="Book ID to retrieve")

class QueryParams(BaseModel):
    include_author: bool | None = Field(default=None, description="Include author details")

class BookResponse(BaseModel):
    id: str
    title: str

class BookView(APIView):
    @docs(errors=[NotFoundError, BadRequestError], path=PathParams, query=QueryParams)
    def get(self, request, book_id: str) -> BookResponse:
        """
        Retrieve a book by ID.

        Returns the book details including title and metadata.
        """
        ...

Multiple Response Types

Use union types to define multiple possible responses:

class SuccessResponse(BaseModel):
    data: dict
    model_config = {"status_code": 200}

class PartialResponse(BaseModel):
    data: dict
    errors: list[str]
    model_config = {"status_code": 207}

class BookView(APIView):
    @docs(response=SuccessResponse | PartialResponse)
    def get(self, request) -> SuccessResponse | PartialResponse:
        ...

Referencing External OpenAPI Components

Use RefType to reference models from other services' OpenAPI schemas:

from drf_pydantic_openapi.ref_utils import RefType

# Simple reference
BookModel = RefType("service_B", "BookModel")

class BookView(APIView):
    def get(self, request) -> BookModel:
        ...

Extending Referenced Types

class CustomBookModel(RefType("service_B", "BookModel")):
    # Add new fields
    read_count: int

    model_config = {
        # Remove fields from referenced type
        "ref_exclude": ("author", "internal_id"),
        # Rename fields: (new_name, original_name)
        "ref_rename": (("name", "book_name"),),
    }

class PaginatedBookModel(BaseModel):
    total: int
    next: str | None
    prev: str | None
    data: list[CustomBookModel]

class BookListView(APIView):
    def get(self, request) -> PaginatedBookModel:
        ...

Typed Exception Handler

Configure the exception handler to return typed error responses:

# settings.py
REST_FRAMEWORK = {
    "EXCEPTION_HANDLER": "drf_pydantic_openapi.exception_handler.typed_exception_handler"
}

Usage:

from drf_pydantic_openapi.errors import BadRequestError, HttpError
from pydantic import BaseModel

# Using built-in errors
class SomeView(APIView):
    @docs(errors=[BadRequestError])
    def post(self, request):
        raise BadRequestError(message="Invalid input")

# Custom error with custom response model
class ValidationErrorResponse(BaseModel):
    message: str
    fields: dict[str, str]

class ValidationError(HttpError):
    status_code = 422
    ResponseModel = ValidationErrorResponse

class SomeView(APIView):
    @docs(errors=[ValidationError])
    def post(self, request):
        raise ValidationError(message="Validation failed", fields={"email": "Invalid format"})

Response format:

{
    "detail": {
        "message": "Bad request"
    }
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_pydantic_openapi-0.6.5.tar.gz (931.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drf_pydantic_openapi-0.6.5-py3-none-any.whl (939.3 kB view details)

Uploaded Python 3

File details

Details for the file drf_pydantic_openapi-0.6.5.tar.gz.

File metadata

  • Download URL: drf_pydantic_openapi-0.6.5.tar.gz
  • Upload date:
  • Size: 931.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.12 Darwin/25.2.0

File hashes

Hashes for drf_pydantic_openapi-0.6.5.tar.gz
Algorithm Hash digest
SHA256 1bf619a2e10aadb188fe61f10e51faf600f89103f753d733834825fd5335ba2b
MD5 2606f5889b2b5ab3b11093e008afc971
BLAKE2b-256 1e23f4db734b77a3ff91d102fe41c4964b508faed136cf7ea4ce8b1ff0abc72a

See more details on using hashes here.

File details

Details for the file drf_pydantic_openapi-0.6.5-py3-none-any.whl.

File metadata

File hashes

Hashes for drf_pydantic_openapi-0.6.5-py3-none-any.whl
Algorithm Hash digest
SHA256 778042bb213677b0dd0f495c4d7db1ec9e142773be9b639ef9cf272d7aff0b56
MD5 699f1ad7ac5fcdae423c9713e01fff00
BLAKE2b-256 5c853f9c26c1d399842a25fc2b3443934f8b2815ef2b34c6f909ff98f13ac8ea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page