Skip to main content

Stop duplicating your Pydantic schemas. Map FastAPI request parameters into a single DTO.

Project description

🎩 FastAPI Magic DTO

Python FastAPI Pydantic License: MIT

Stop duplicating your Pydantic schemas. Keep your Application layer pure.

fastapi-magic-dto is a lightweight utility that allows you to map FastAPI request parameters (Path, Query, Header, Cookie, and Body) directly into a single, clean DTO (Data Transfer Object) without polluting your business logic with HTTP-specific dependencies.

🤬 The Problem

When building layered architectures (Clean Architecture, CQRS, Hexagonal), your Application layer (Interactors/Use Cases) should know nothing about HTTP.

Normally, to extract data from multiple HTTP locations (like a User ID from the URL Path, and the User Name from the JSON Body), FastAPI forces you to either:

  1. Write two separate schemas (one for FastAPI, one for the Application layer) and map them manually.
  2. Pollute your Application DTO with fastapi.Path and fastapi.Query.

❌ Bad (Leaking HTTP into Domain)

from fastapi import Path, Body
from pydantic import BaseModel

class UpdateUserDTO(BaseModel):
    user_id: int = Path(...)  # 🔴 Domain now depends on FastAPI!
    name: str = Body(...)

✨ The Solution

fastapi-magic-dto allows you to write a pure Pydantic DTO (or standard Dataclass), and use an elegant type hint at the Router level to tell FastAPI exactly where to find the data.

✅ Good (Pure Domain + MagicDTO)

from pydantic import BaseModel
from fastapi_magic_dto import MagicDTO, P

# 1. Pure Application DTO. Zero HTTP logic.
class UpdateUserDTO(BaseModel):
    user_id: int
    name: str

# 2. FastAPI Router mapping HTTP to the DTO
@app.put("/users/{user_id}")
async def update_user(
    data: MagicDTO[UpdateUserDTO, P.user_id]
):
    # `user_id` is extracted from the URL Path.
    # `name` is automatically extracted from the JSON Body.
    return data

📦 Installation

pip install fastapi-magic-dto

🚀 Features

  • Zero Duplication: Write one DTO for both validation and business logic.
  • Perfect OpenAPI (Swagger): Fully compatible with FastAPI's automatic schema generation. Path, Query, and Body parameters appear exactly where they should.
  • Type Checker Friendly: Mypy, Pylance, and Pyright will see the correct types. Autocomplete works perfectly.
  • Dataclass Support: Works natively with standard Python @dataclass—no Pydantic required!
  • Everything Supported: Extract data from Path (P), Query (Q), Header (H), Cookie (C), and JSON Body.

🛠 Usage & Markers

The library provides 4 intuitive markers to define the origin of your fields:

Marker HTTP Location Example
P Path P.item_id maps to /items/{item_id}
Q Query Q.limit maps to ?limit=10
H Header H.user_agent maps to User-Agent: ...
C Cookie C.session maps to Cookie: session=...

Note: Any field in your DTO that is not explicitly marked will automatically be extracted from the JSON Request Body.

📖 Complete Example (The Frankenstein)

You can extract data from everywhere simultaneously into a single DTO.

class CreateItemDTO(BaseModel):
    category_id: int
    name: str = Field(..., min_length=2, max_length=100)
    price: float = Field(...)


class CreateItemInteractor:
    async def __call__(self, data: CreateItemDTO) -> dict:
        # Business logic goes here (e.g., saving to the database)
        return {
            "status": "success",
            "message": f"Item '{data.name}' created in category {data.category_id}.",
            "item_data": data.model_dump(),
        }


create_item_interactor = CreateItemInteractor()

app = FastAPI()


@app.post("/items/{category_id}", tags=["Items"])
async def create_item(
    # MagicDTO extracts `category_id` from Path, and `name`/`price` from Body
    data: MagicDTO[CreateItemDTO, P.category_id],
) -> dict:
    return await create_item_interactor(data)

🐍 Using Standard Dataclasses

Don't want to use Pydantic? No problem. MagicDTO fully supports standard Python dataclasses.

from dataclasses import dataclass
from fastapi_magic_dto import MagicDTO, P, Q

@dataclass
class SearchDTO:
    category_id: int
    limit: int = 10
    search_term: str = ""

@app.get("/search/{category_id}")
async def search_items(
    data: MagicDTO[SearchDTO, P.category_id, Q.limit, Q.search_term]
):
    return data

📝 License

MIT License. See LICENSE for details.

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

fastapi_magic_dto-0.1.0.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

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

fastapi_magic_dto-0.1.0-py3-none-any.whl (6.5 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_magic_dto-0.1.0.tar.gz.

File metadata

  • Download URL: fastapi_magic_dto-0.1.0.tar.gz
  • Upload date:
  • Size: 16.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.10 {"installer":{"name":"uv","version":"0.9.10"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastapi_magic_dto-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a152e2fee005a7289735284be2bac97a99161781094ccd6a977184dc1d869f87
MD5 e6aa63abdbae48563fd966cfec51a9df
BLAKE2b-256 af61cdfaf138dd167dd5a445904bd6e58bcaff51c53caab0cfd75d1ac7358396

See more details on using hashes here.

File details

Details for the file fastapi_magic_dto-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fastapi_magic_dto-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.10 {"installer":{"name":"uv","version":"0.9.10"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastapi_magic_dto-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1feae9f2e4374b5d3c3acc1e220d3b127e61499df9ca96a290ccc9570449faa2
MD5 ce8155d91671296a177b8f29451c7ea9
BLAKE2b-256 70bd56f4c03a73bf2cd95fcde845fe1598fcdd7839dff0b9ac1cba78e50c5688

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