plugins/litestar/skills/litestar-dto/SKILL.md
Configure Litestar DTO behavior for inbound parsing and outbound serialization, including layer-scoped `dto`/`return_dto`, `DTOConfig` policies, `DTOData` update workflows, and custom `AbstractDTO` implementations. Use when API payload contracts differ from internal model structures. Do not use when internal models can be exposed safely without transformation.
npx skillsauth add alti3/litestar-skills litestar-dtoInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when request and response payloads need explicit shape control, field-level policy, or DTO factory customization.
dto) and outbound (return_dto) behavior explicitly.DataclassDTO, SQLAlchemyDTO, or plugin-provided DTOs).DTOConfig (exclude, rename, nesting depth, unknown-field handling, PATCH behavior).DTOData[T] in write/update handlers when you need controlled instantiation and patching semantics.Response[T], pagination, generic wrappers) to ensure DTO transformation is still applied.AbstractDTO only when factory DTOs cannot express required behavior.forbid_unknown_fields=True) in stricter API surfaces.id, audit fields).Litestar exposes two DTO parameters on each app layer:
dto: inbound parsing for handler data; if return_dto is not set, this is also used for outbound serialization.return_dto: outbound serialization policy only.DTOs can be declared on handler, controller, router, or application. The DTO closest to the handler in the ownership chain applies.
Common pattern:
dto=WriteDTO to parse inbound payloads.return_dto=ReadDTO to serialize outbound payloads.return_dto=None on handlers where DTO serialization should be disabled (for example, DELETE -> None).DTOConfig Policy GuideUse DTOConfig to define stable contract rules:
exclude={...}: remove fields (supports nested paths, including list-item paths such as "pets.0.id").rename_fields={...}: rename specific fields.rename_strategy="camel" (or callback): apply systematic renaming.max_nested_depth: control nested parsing/serialization depth (1 default shown in docs).forbid_unknown_fields=True: reject extra payload fields instead of silently ignoring them.partial=True: PATCH-friendly DTO behavior.leading_underscore_private=False only when you intentionally want underscore-prefixed fields treated as public.experimental_codegen_backend=False to selectively disable codegen backend behavior.Important behavior:
rename_fields mappings are not further transformed by rename_strategy.Use dto_field(...) metadata to mark model fields with DTO semantics:
"private": not parsed from inbound data and never serialized in outbound data."read-only": not parsed from inbound data.Also note:
DTOData[T]: Controlled Create and Update FlowsUse DTOData[T] for create/update handlers that need controlled model mutation:
data.create_instance(...) creates model instances from validated input and can inject server-side values.address__id=...) when excluded nested fields must still be set.data.update_instance(existing) supports partial updates cleanly for PATCH workflows when partial=True.PATCH pattern:
id) in DTO config.DTOData.update_instance() to apply only submitted fields.DTO factory types can transform data inside supported wrappers:
WithCount[T]) when one type parameter maps to DTO-supported model data.ClassicPagination[T] (DTO applies to items).Response[T] wrappers (DTO applies to content).DTO codegen backend:
2.2.0, stabilized and enabled by default in 2.8.0.DTOConfig(experimental_codegen_backend=...).Use selective override only when debugging compatibility or behavior differences.
Use built-in DTO factories first. Create custom DTO classes only when required behavior is not expressible via existing DTO factories + DTOConfig.
When implementing custom DTOs, you must implement AbstractDTO methods:
generate_field_definitions(model_type): yield DTOFieldDefinition objects for DTO-visible fields.detect_nested_field(field_definition): return whether the field represents nested model data.This is the minimal protocol Litestar requires for custom DTO implementations.
from litestar import get, patch
from litestar.dto import DTOConfig, DTOData, DataclassDTO
class UserReadDTO(DataclassDTO[User]):
config = DTOConfig(exclude={"password_hash"})
class UserPatchDTO(DataclassDTO[User]):
# Patch DTO excludes immutable id and accepts partial payloads.
config = DTOConfig(exclude={"id"}, partial=True)
@get("/users/{user_id:int}", return_dto=UserReadDTO)
async def get_user(user_id: int) -> User:
return ...
@patch("/users/{user_id:int}", dto=UserPatchDTO, return_dto=UserReadDTO)
async def patch_user(user_id: int, data: DTOData[User]) -> User:
user = ...
return data.update_instance(user)
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
class PublicUserDTO(SQLAlchemyDTO[User]):
config = DTOConfig(exclude={"password_hash"})
dto and return_dto are intentionally selected (or explicitly disabled) per handler.forbid_unknown_fields).partial=True + DTOData.update_instance() where appropriate.Response, pagination, generic envelopes) still apply DTO transformations.litestar-dataclasses, litestar-plugins, or litestar-custom-types for model ecosystem specifics.litestar-databases when DTO behavior couples to SQLAlchemy or Piccolo persistence design.litestar-openapi to verify generated schema accuracy after DTO changes.litestar-requests and litestar-responses for transport-level behavior outside DTO transformation.development
Build Litestar WebSocket endpoints with low-level websocket handlers, websocket listeners, websocket streams, dependency injection, custom websocket classes, transport-mode control, and graceful connection lifecycle handling. Use when implementing bidirectional real-time communication, reactive websocket message handling, or proactive server push over WebSockets. Do not use for server-side pub/sub fanout that is better expressed with channels alone.
tools
Test Litestar applications with TestClient, AsyncTestClient, create_test_client, websocket test helpers, dependency overrides, mocked dependencies, lifecycle-aware fixtures, and deterministic success and failure assertions. Use when adding or fixing Litestar test coverage, including exception contracts, override precedence, websocket behavior, event-bus side effects, or live-server-only response patterns. Do not use as a substitute for production observability or runtime debugging strategy.
development
Configure Litestar templating with `TemplateConfig`, Jinja/Mako/MiniJinja engines, file-or-string `Template` responses, request and CSRF-aware context, template callables, and custom engine integration. Use when implementing or fixing server-rendered HTML in Litestar. Do not use for static asset serving or pure JSON API endpoints.
development
Configure Litestar stores and the store registry for caching, server-side sessions, rate limiting, and other key-value state with explicit backend selection, bytes-safe data handling, TTL and renewal policy, namespacing, registry wiring, and lifecycle cleanup. Use when a Litestar app depends on `MemoryStore`, `FileStore`, `RedisStore`, `ValkeyStore`, or `StoreRegistry`. Do not use for relational persistence, domain repositories, or response-caching policy details that belong in database or caching-focused skills.