pydantic-models-py

star 55

Pydantic Models workflow skill. Use this skill when the user needs Create Pydantic models following the multi-model pattern for clean API contracts and the operator should design explicit request, update, response, and internal model boundaries before merging or handing off.

diegosouzapw By diegosouzapw schedule Updated 6/2/2026

name: "pydantic-models-py" description: "Pydantic Models workflow skill. Use this skill when the user needs Create Pydantic models following the multi-model pattern for clean API contracts and the operator should design explicit request, update, response, and internal model boundaries before merging or handing off." version: "0.0.1" category: "machine-learning" tags: - "pydantic-models-py" - "pydantic" - "api-contracts" - "request-models" - "response-models" - "patch-updates" - "omni-enhanced" complexity: "advanced" risk: "safe" tools: - "codex-cli" - "claude-code" - "cursor" - "gemini-cli" - "opencode" source: "omni-team" author: "Omni Skills Team" date_added: "2026-03-27" date_updated: "2026-04-19" source_type: "omni-curated" maintainer: "Omni Skills Team" family_id: "pydantic-models-py" family_name: "Pydantic Models" variant_id: "omni" variant_label: "Omni Curated" is_default_variant: true derived_from: "skills/pydantic-models-py" upstream_skill: "skills/pydantic-models-py" upstream_author: "sickn33" upstream_source: "community" upstream_pr: "79" upstream_head_repo: "diegosouzapw/awesome-omni-skills" upstream_head_sha: "6bf093920a93e68fa8263cf6ee767d7407989d56" curation_surface: "skills_omni" enhanced_origin: "omni-skills-private" source_repo: "diegosouzapw/awesome-omni-skills" replaces: - "pydantic-models-py"

Pydantic Models

Overview

Use this skill to create or refactor Pydantic models for API integration work where request and response contracts must stay explicit, stable, and safe.

The upstream intent is preserved: use a multi-model pattern instead of one overloaded model for every purpose. The enhanced workflow modernizes that pattern for Pydantic v2 and focuses on operational API contract design:

  • separate create, update, public response, and internal shapes when their contracts differ
  • use aliases intentionally when wire format differs from Python naming
  • treat PATCH semantics as distinct from create semantics
  • adapt ORM or document objects with from_attributes=True instead of legacy orm_mode
  • prevent accidental field leakage by serializing public models, not internal ones

This skill is framework-agnostic Python guidance. FastAPI-style patterns are referenced because they are common and well documented, but the workflow applies to general API integration work.

Version guard: this workflow assumes Pydantic v2 semantics such as model_validate, model_dump, ConfigDict, field_validator, and from_attributes.

When to Use This Skill

Use this skill when:

  • you need Pydantic models for an external or internal API contract
  • one model is starting to mix input validation, storage fields, and response serialization concerns
  • the task requires separate handling for create vs update vs response payloads
  • the API uses a different field naming style on the wire, such as camelCase externally and snake_case in Python
  • partial updates must preserve the difference between omitted fields and explicit null
  • ORM, document, or service-layer objects must be adapted into response models safely

Do not use this skill as the primary router when:

  • the user only needs a single ad hoc data container with no contract boundary concerns
  • the task is mainly about database schema design rather than API payload design
  • the task depends on framework-specific response plumbing more than on Pydantic model design

Operating Table

Situation Recommended model family Key choices Primary methods Main risk
Create or POST request Create / input model required writable fields, extra='forbid', clear constraints model_validate(...) accepting undeclared fields or weak validation
Partial update or PATCH request Update model all fields optional as transport inputs, use exclude_unset=True model_dump(exclude_unset=True) clearing stored values by mistake
Public API response Public / Read model expose only contract fields, serialize with aliases if wire format needs them model_validate(...), model_dump(by_alias=True) leaking internal fields or wrong field names
Internal service response Internal model include operational metadata only if not public model_validate(...), model_dump(...) reusing internal models as public DTOs
ORM or document adaptation Public or Internal model with attribute adaptation from_attributes=True when validating from objects model_validate(obj) legacy orm_mode assumptions or field shape mismatch
Persistence shape separate InDB / persistence model only if contract differs materially add store-only fields only when needed validate near persistence boundary unnecessary model sprawl

For selection guidance and config tradeoffs, see references/integration-patterns.md.

Workflow

  1. Identify contract boundaries before writing code. Decide whether the task truly needs separate models for create, update, public response, internal response, or persistence. Do not create extra model families unless the payloads differ in a way that matters.

  2. Start from the external contract, not the database shape. For API work, define what clients may send and receive first. Persistence-only fields such as internal IDs, doc_type, audit flags, revision tokens, or secret material should not appear in public response models unless explicitly required.

  3. Choose a model taxonomy. A practical default is:

    • ThingBase: shared constraints only when reuse is genuinely helpful
    • ThingCreate: fields accepted on creation
    • ThingUpdate: partial-update transport model
    • ThingPublic: fields returned to API clients
    • ThingInternal or ThingInDB: only when internal or persistence needs differ materially

    If Base inheritance makes public/private boundaries fuzzy, prefer separate models instead of inheritance.

  4. Set explicit config for request safety. For externally sourced request models, start conservative:

    from pydantic import BaseModel, ConfigDict
    
    class WidgetCreate(BaseModel):
        model_config = ConfigDict(extra='forbid')
    

    Consider stricter settings intentionally. Reject undeclared fields unless you have a compatibility reason not to. Use default_factory for dynamic defaults instead of mutable literals.

  5. Define field naming policy and aliases deliberately. If Python code uses snake_case but the API contract uses camelCase, encode that policy explicitly. Be consistent about whether validation accepts Python names, wire aliases, or both.

    Preferred rule of thumb:

    • keep Python attributes idiomatic in code
    • expose the wire contract through aliases
    • serialize public payloads with by_alias=True when aliases define the contract
    • avoid mixing ad hoc field-level aliasing and broad alias generators without a reason
  6. Separate create and update semantics. Create models usually express required writable fields. Update models usually make all updatable fields optional so the transport layer can represent omission.

    Important distinction:

    • omitted field: leave current stored value unchanged
    • field present with null / None: clear it, if the contract allows
    • field present with value: replace or update

    Use model_dump(exclude_unset=True) when applying PATCH-like updates.

  7. Validate and adapt at the correct boundary. Use model_validate(...) when building models from request payloads, trusted dictionaries, or class instances. When validating from ORM or document objects, configure the target model with from_attributes=True.

  8. Serialize public responses from public models. Prefer:

    • validate an internal object into ThingPublic
    • serialize ThingPublic with model_dump(by_alias=True) if aliases define the contract

    Avoid dumping a richer internal model and trying to hide fields with ad hoc exclude lists.

  9. Place business rules carefully. Use field_validator or model_validator for transport and shape validation that belongs to the data contract. Keep workflow-specific side effects, repository checks, and cross-service orchestration in endpoint or service logic.

  10. Check generated payloads explicitly. Before finalizing, verify:

    • required vs optional fields match the real contract
    • public output excludes internal metadata
    • aliases serialize exactly as clients expect
    • PATCH behavior preserves omitted fields

Troubleshooting

Incoming camelCase fields do not populate snake_case model fields

Symptoms

  • requests fail validation even though field names look correct to the client
  • response output uses the wrong field style

Likely causes

  • aliases were defined but serialization is not using by_alias=True
  • validation settings do not match the accepted request field style
  • alias strategy is mixed inconsistently across fields

Corrective actions

  • define one alias policy for the model family
  • ensure the public serialization path uses model_dump(by_alias=True) when aliases define the API contract
  • avoid silently accepting multiple naming styles unless compatibility requires it

PATCH or update requests clear values unexpectedly

Symptoms

  • omitted fields overwrite stored data with None
  • updates behave like full replacement instead of partial modification

Likely causes

  • create and update models are being reused as if they were identical
  • update application logic uses the full dumped model instead of exclude_unset=True
  • explicit None is not being distinguished from field omission

Corrective actions

  • create a dedicated Update model
  • apply updates using model_dump(exclude_unset=True)
  • decide explicitly whether None means clear-the-value or invalid input for each field

ORM or document objects fail validation

Symptoms

  • validation errors occur when passing model instances or row objects into response models
  • nested attributes do not serialize as expected

Likely causes

  • target model is missing from_attributes=True
  • attribute names on the object do not match the response model fields or aliases
  • the object contains richer nested state than the response contract allows

Corrective actions

  • enable attribute-based validation on the target response model
  • validate into a public DTO rather than serializing the raw ORM object
  • inspect field names and nested object shapes before assuming the failure is a Pydantic bug

Extra fields are accepted or rejected unexpectedly

Symptoms

  • clients can send undeclared fields without error
  • valid-looking requests fail because of unrecognized keys

Likely causes

  • extra handling was left implicit
  • request compatibility expectations are unclear

Corrective actions

  • set extra='forbid' for external request models unless a looser contract is intentional
  • document any compatibility exceptions clearly
  • do not use permissive extra handling as a shortcut for poor contract definition

Public responses leak internal metadata

Symptoms

  • internal IDs, persistence fields, or operational flags appear in API output

Likely causes

  • internal and public models were merged for convenience
  • responses are serialized from internal models with ad hoc exclusions

Corrective actions

  • create a dedicated public response model
  • validate internal data into the public model before serialization
  • verify the exact wire payload with model_dump(by_alias=True) when aliases are used

Examples

See examples/request-response-example.md for a complete worked example that includes:

  • separate create, update, public, internal, and persistence-adaptation models
  • a camelCase wire contract with snake_case Python attributes
  • extra='forbid' on request models
  • from_attributes=True for adapting an object into a public DTO
  • a PATCH scenario showing omitted vs explicit null

Additional Resources

  • references/integration-patterns.md — model-family selection matrix, alias policy options, config defaults, and contract safety guidance
  • Pydantic v2 documentation for models, config, aliases, serialization, validators, and attribute-based validation
  • FastAPI documentation on extra models and body updates for common API usage patterns
  • JSON Schema and OpenAPI references for contract-oriented field semantics

Related Skills

Use related skills when the task drifts into:

  • framework-specific endpoint wiring rather than model design
  • database migrations or persistence schema design
  • TypeScript client generation or OpenAPI publication workflow

When in doubt, keep this skill focused on Pydantic model boundaries and API contract correctness rather than general backend implementation.

Install via CLI
npx skills add https://github.com/diegosouzapw/awesome-omni-skills --skill pydantic-models-py
Repository Details
star Stars 55
call_split Forks 11
navigation Branch main
article Path SKILL.md
More from Creator
diegosouzapw
diegosouzapw Explore all skills →