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 modelerrors: List of error modelsquery: Query parameters modelpath: Path parameters modelresponse: 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bf619a2e10aadb188fe61f10e51faf600f89103f753d733834825fd5335ba2b
|
|
| MD5 |
2606f5889b2b5ab3b11093e008afc971
|
|
| BLAKE2b-256 |
1e23f4db734b77a3ff91d102fe41c4964b508faed136cf7ea4ce8b1ff0abc72a
|
File details
Details for the file drf_pydantic_openapi-0.6.5-py3-none-any.whl.
File metadata
- Download URL: drf_pydantic_openapi-0.6.5-py3-none-any.whl
- Upload date:
- Size: 939.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.12.12 Darwin/25.2.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
778042bb213677b0dd0f495c4d7db1ec9e142773be9b639ef9cf272d7aff0b56
|
|
| MD5 |
699f1ad7ac5fcdae423c9713e01fff00
|
|
| BLAKE2b-256 |
5c853f9c26c1d399842a25fc2b3443934f8b2815ef2b34c6f909ff98f13ac8ea
|