Validation
Austial’s validation story leans entirely on FastAPI/pydantic — DTOs are
just pydantic BaseModel classes, type-hinted as a handler’s = Body()
parameter, exactly the shape you’d already reach for in plain FastAPI.
Defining a DTO
from pydantic import BaseModel
class CreateCatDto(BaseModel):
name: str
class UpdateCatDto(BaseModel):
name: str | None = None@Post()
async def create(self, dto: CreateCatDto = Body()) -> Cat:
return self.service.create(dto)FastAPI parses and validates the incoming JSON body against CreateCatDto
before your handler is even called — a request missing name, or with the
wrong type, never reaches create().
ValidationPipe
from austial.common.pipes import ValidationPipe
app.use_global_pipes(ValidationPipe())Registering ValidationPipe globally (as every austial new project does
by default in src/main.py) ensures validation failures come back in the
same error body shape as every other exception in the app:
{
"statusCode": 400,
"message": ["field required: name"],
"error": "Bad Request"
}See Pipes for the full PipeTransform reference if you
need custom transformation/validation logic beyond what pydantic gives you
for free.
Nested and reused DTOs
Because DTOs are plain pydantic models, everything pydantic supports —
nested models, Field(...) constraints, custom validators, model_config
— works exactly as it does in a plain FastAPI app:
from pydantic import BaseModel, Field
class Address(BaseModel):
street: str
city: str
class CreateCustomerDto(BaseModel):
name: str = Field(min_length=1, max_length=100)
address: AddressThere’s no separate Austial-specific validation DSL to learn on top of this — the framework’s job stops at wiring pydantic’s own validation into the consistent error response format.