DTO Validation with Pydantic¶
Cello has first-class support for Pydantic models as handler parameters. When a Pydantic model is declared as a type-annotated argument, Cello automatically deserialises and validates the incoming JSON body before your handler is ever called. This example also gracefully handles environments where Pydantic is not installed.
Features Demonstrated¶
- Declaring a
BaseModelsubclass as a Data Transfer Object (DTO) - Using Pydantic's
EmailStrfor validated email fields - Injecting a validated DTO directly into a route handler signature
- Graceful fallback when Pydantic is unavailable at runtime
Complete Source Code¶
from cello import App, Response
try:
from pydantic import BaseModel, EmailStr
HAS_PYDANTIC = True
except ImportError:
HAS_PYDANTIC = False
app = App()
if HAS_PYDANTIC:
class CreateUserDTO(BaseModel):
username: str
email: EmailStr
age: int
@app.post("/users")
def create_user(request, user: CreateUserDTO):
return {"status": "created", "user": user.dict()}
else:
@app.post("/users")
def create_user(request):
return {"error": "Pydantic missing"}
if __name__ == "__main__":
app.run(port=8080)
Running This Example¶
python examples/dto_validation.py
# then test it:
curl -X POST http://127.0.0.1:8080/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "email": "alice@example.com", "age": 30}'
Key Concepts¶
- DTO injection — Annotate a handler parameter with a Pydantic model type and Cello will parse, validate, and inject the model instance automatically.
- Validation errors — If the request body fails Pydantic validation (e.g., missing fields, wrong types, invalid email), Cello returns a
422 Unprocessable Entityresponse with detailed error information before your code runs. EmailStr— A Pydantic field type that verifies the value is a syntactically valid email address, requiring theemail-validatorpackage.- Optional dependency pattern — Wrapping the import in a
try/exceptblock and checkingHAS_PYDANTIClets the module load cleanly even without Pydantic installed, making it easy to ship an informative fallback response.