[{"data":1,"prerenderedAt":100},["ShallowReactive",2],{"qa-\u002Ffastapi\u002Fpydantic\u002Fmodels":3},{"page":4,"siblings":87,"blog":78},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":77,"related":78,"seo":79,"seoDescription":80,"stem":81,"subtopic":82,"topic":83,"topicSlug":84,"updated":85,"__hash__":86},"qa\u002Ffastapi\u002Fpydantic\u002Fmodels.md","Models",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","FastAPI","fastapi",{},true,1,"\u002Ffastapi\u002Fpydantic\u002Fmodels",[23,28,32,36,40,44,48,52,56,60,64,68,72],{"id":24,"difficulty":25,"q":26,"a":27},"basemodel-basics","easy","What is Pydantic's `BaseModel` and why does FastAPI rely on it?","`BaseModel` is Pydantic's foundation class. Subclasses declare fields as\nclass-level annotations; Pydantic validates and coerces incoming data at\ninstantiation time.\n\n```python\nfrom pydantic import BaseModel\n\nclass Item(BaseModel):\n    name: str\n    price: float\n    quantity: int = 1    # default value\n\nitem = Item(name=\"Widget\", price=9.99)\n# Item(name='Widget', price=9.99, quantity=1)\n\nItem(name=\"Widget\", price=\"nine\")   # raises ValidationError: price must be float\n```\n\nFastAPI uses `BaseModel` to:\n1. Parse and validate incoming JSON bodies.\n2. Serialise outgoing responses.\n3. Generate OpenAPI JSON Schema.\n\nRule of thumb: use a `BaseModel` subclass for any structured data that crosses\nthe HTTP boundary — it's free validation and documentation.\n",{"id":29,"difficulty":25,"q":30,"a":31},"field-defaults","How do you add metadata (description, example, constraints) to a Pydantic field?","Use `Field()` from Pydantic:\n\n```python\nfrom pydantic import BaseModel, Field\n\nclass Product(BaseModel):\n    name: str = Field(min_length=1, max_length=100, description=\"Product name\")\n    price: float = Field(gt=0, description=\"Price in USD\", example=9.99)\n    sku: str = Field(pattern=r\"^[A-Z]{3}-\\d{4}$\", examples=[\"ABC-1234\"])\n```\n\n`Field()` parameters:\n- Constraints: `gt`, `ge`, `lt`, `le`, `min_length`, `max_length`, `pattern`, `multiple_of`\n- Metadata: `title`, `description`, `example`, `examples`\n- Behaviour: `default`, `default_factory`, `alias`, `exclude`\n\nRule of thumb: use `Field()` for any field that needs a constraint or a helpful\ndescription — it ends up in the OpenAPI schema and saves clients guessing.\n",{"id":33,"difficulty":25,"q":34,"a":35},"required-vs-optional","How do you mark a Pydantic field as required vs optional?","- **Required**: no default value — Pydantic raises `ValidationError` if omitted.\n- **Optional with None**: `field: T | None = None` — accepts `None` or the type.\n- **Optional with default**: `field: T = default_value`.\n\n```python\nfrom pydantic import BaseModel\n\nclass User(BaseModel):\n    id: int                      # required\n    name: str                    # required\n    bio: str | None = None       # optional, defaults to None\n    role: str = \"viewer\"         # optional, defaults to \"viewer\"\n```\n\nIn OpenAPI:\n- Required fields → `required: [...]` array in the schema.\n- Optional fields → absent from `required`, with `default` or `nullable`.\n\nRule of thumb: think of `None` default as \"not provided\"; use a semantic default\nlike `\"viewer\"` when the field has a meaningful fallback value.\n",{"id":37,"difficulty":14,"q":38,"a":39},"field-alias","What is a field alias in Pydantic and when would you use it?","An alias lets the JSON key differ from the Python attribute name. Useful when\nthe API uses camelCase, hyphens, or reserved Python keywords.\n\n```python\nfrom pydantic import BaseModel, Field\n\nclass Order(BaseModel):\n    order_id: int = Field(alias=\"orderId\")        # JSON: \"orderId\"\n    item_count: int = Field(alias=\"itemCount\")\n\n# Parsing from JSON (camelCase input)\norder = Order.model_validate({\"orderId\": 42, \"itemCount\": 3})\nprint(order.order_id)  # 42   (Python snake_case attribute)\n```\n\nFor global camelCase ↔ snake_case conversion use `model_config`:\n```python\nfrom pydantic import ConfigDict\n\nclass MyModel(BaseModel):\n    model_config = ConfigDict(alias_generator=lambda s: s.replace(\"_\", \"\"), populate_by_name=True)\n    order_id: int\n```\n\nRule of thumb: use `alias` for a few fields; use `alias_generator` when the\nentire API uses camelCase (common with JavaScript clients).\n",{"id":41,"difficulty":14,"q":42,"a":43},"model-inheritance","How does Pydantic model inheritance work and what are its use cases in FastAPI?","A child model inherits all fields from its parent and can add or override them.\n\n```python\nclass ItemBase(BaseModel):\n    name: str\n    price: float\n\nclass ItemCreate(ItemBase):\n    # used for POST body — no id yet\n    pass\n\nclass ItemUpdate(ItemBase):\n    # all fields optional for PATCH\n    name: str | None = None\n    price: float | None = None\n\nclass ItemOut(ItemBase):\n    id: int            # added by DB\n    created_at: datetime\n```\n\nThis pattern keeps field definitions DRY while giving each use-case the exact\nshape it needs.\n\nRule of thumb: define a `Base` model with shared fields, then derive `Create`,\n`Update`, and `Out` variants — the \"Input\u002FOutput DTO\" pattern.\n",{"id":45,"difficulty":14,"q":46,"a":47},"model-config","What is `model_config` in Pydantic v2 and what can you configure with it?","`model_config = ConfigDict(...)` replaces Pydantic v1's inner `class Config`.\nKey options:\n\n| Setting | Effect |\n|---------|--------|\n| `extra=\"forbid\"` | Reject extra fields |\n| `frozen=True` | Make instances immutable (hashable) |\n| `populate_by_name=True` | Allow both alias and name |\n| `from_attributes=True` | Parse from ORM objects (SQLAlchemy) |\n| `str_strip_whitespace=True` | Auto-strip leading\u002Ftrailing spaces |\n| `alias_generator=fn` | Auto-generate aliases for all fields |\n\n```python\nfrom pydantic import BaseModel, ConfigDict\n\nclass StrictUser(BaseModel):\n    model_config = ConfigDict(extra=\"forbid\", frozen=True)\n    id: int\n    name: str\n```\n\nRule of thumb: set `from_attributes=True` on any model that reads from SQLAlchemy\nORM objects; set `extra=\"forbid\"` on request models to catch client typos.\n",{"id":49,"difficulty":14,"q":50,"a":51},"orm-mode","What is `from_attributes=True` (formerly `orm_mode`) and why is it needed?","By default Pydantic models only parse from dicts. `from_attributes=True` allows\nparsing from any object with attributes — including SQLAlchemy ORM instances.\n\n```python\nfrom pydantic import BaseModel, ConfigDict\nfrom sqlalchemy import Column, Integer, String\nfrom sqlalchemy.orm import DeclarativeBase\n\nclass Base(DeclarativeBase): pass\n\nclass UserORM(Base):\n    __tablename__ = \"users\"\n    id = Column(Integer, primary_key=True)\n    name = Column(String)\n\nclass UserOut(BaseModel):\n    model_config = ConfigDict(from_attributes=True)\n    id: int\n    name: str\n\nuser_orm = session.get(UserORM, 1)\nuser_out = UserOut.model_validate(user_orm)   # reads .id and .name attributes\n```\n\nWithout `from_attributes=True`, `model_validate(orm_obj)` raises a\n`ValidationError` because ORM objects aren't dicts.\n\nRule of thumb: always set `from_attributes=True` on output schemas that will\nbe constructed from SQLAlchemy models.\n",{"id":53,"difficulty":14,"q":54,"a":55},"computed-field","How do you add a computed (read-only) field to a Pydantic model?","Use `@computed_field` (Pydantic v2):\n\n```python\nfrom pydantic import BaseModel, computed_field\n\nclass Rectangle(BaseModel):\n    width: float\n    height: float\n\n    @computed_field\n    @property\n    def area(self) -> float:\n        return self.width * self.height\n\nr = Rectangle(width=3.0, height=4.0)\nprint(r.area)           # 12.0\nprint(r.model_dump())   # {\"width\": 3.0, \"height\": 4.0, \"area\": 12.0}\n```\n\n`@computed_field` fields are included in serialisation and the OpenAPI schema.\nThey are always read-only — you can't set them from input.\n\nRule of thumb: use `@computed_field` for derived values that belong in the\nresponse (full name from first + last, URL from ID); avoid heavy computation in them.\n",{"id":57,"difficulty":25,"q":58,"a":59},"model-validate","What is `model_validate()` and how does it differ from calling the constructor?","`Model.model_validate(obj)` is the explicit way to parse data in Pydantic v2.\nIt accepts a dict **or** any object (with `from_attributes=True`) and returns a\nvalidated model instance.\n\n```python\n# constructor — same as model_validate for dicts\nitem = Item(name=\"Widget\", price=9.99)\n\n# model_validate — more explicit, required for non-dict input\nitem = Item.model_validate({\"name\": \"Widget\", \"price\": 9.99})\nitem = Item.model_validate(orm_instance)   # needs from_attributes=True\n```\n\nIn FastAPI, `model_validate` is called internally when parsing request bodies.\nYou call it explicitly when converting ORM objects to Pydantic models in service\nor repository layers.\n\nRule of thumb: use the constructor for tests with literal dicts; use\n`model_validate` in production code where the source object might be an ORM row.\n",{"id":61,"difficulty":25,"q":62,"a":63},"model-dump","What does `model_dump()` return and what options does it accept?","`model_dump()` returns a Python dict of the model's fields. It's Pydantic v2's\nreplacement for `.dict()`.\n\n```python\nitem = Item(name=\"Widget\", price=9.99)\nitem.model_dump()\n# {\"name\": \"Widget\", \"price\": 9.99}\n\n# exclude fields\nitem.model_dump(exclude={\"price\"})\n# {\"name\": \"Widget\"}\n\n# only unset fields (for PATCH)\nitem.model_dump(exclude_unset=True)\n\n# JSON-safe output (datetime → str, UUID → str)\nitem.model_dump(mode=\"json\")\n```\n\nRule of thumb: use `model_dump(exclude_unset=True)` in PATCH handlers to get\nonly the fields the client explicitly sent.\n",{"id":65,"difficulty":14,"q":66,"a":67},"model-json-schema","How do you get the JSON Schema for a Pydantic model?","Call `Model.model_json_schema()`:\n\n```python\nimport json\nfrom pydantic import BaseModel, Field\n\nclass Item(BaseModel):\n    name: str = Field(min_length=1)\n    price: float = Field(gt=0)\n\nprint(json.dumps(Item.model_json_schema(), indent=2))\n# {\n#   \"title\": \"Item\",\n#   \"type\": \"object\",\n#   \"properties\": {\n#     \"name\": {\"type\": \"string\", \"minLength\": 1},\n#     \"price\": {\"type\": \"number\", \"exclusiveMinimum\": 0}\n#   },\n#   \"required\": [\"name\", \"price\"]\n# }\n```\n\nFastAPI embeds this schema in `\u002Fopenapi.json` automatically. You might call\n`model_json_schema()` directly to validate schemas in tests or export them to\nother systems.\n\nRule of thumb: write a test that calls `model_json_schema()` and asserts key\nproperties — it catches breaking schema changes before they hit production.\n",{"id":69,"difficulty":14,"q":70,"a":71},"pydantic-v1-vs-v2","What are the key differences between Pydantic v1 and v2 that affect FastAPI code?","| Feature | Pydantic v1 | Pydantic v2 |\n|---------|-------------|-------------|\n| Config | `class Config:` | `model_config = ConfigDict(...)` |\n| ORM mode | `orm_mode = True` | `from_attributes=True` |\n| Serialise | `.dict()` \u002F `.json()` | `.model_dump()` \u002F `.model_dump_json()` |\n| Parse | `MyModel(**data)` \u002F `.parse_obj()` | `.model_validate(data)` |\n| Validators | `@validator` | `@field_validator` \u002F `@model_validator` |\n| Performance | Pure Python | Rust core (10-50× faster) |\n\nFastAPI 0.100+ requires Pydantic v2. Code targeting both versions uses the\n`pydantic.v1` compatibility shim.\n\nRule of thumb: always use Pydantic v2 APIs in new code; if maintaining a\nv1 codebase, migrate validators first (they have the most breaking changes).\n",{"id":73,"difficulty":74,"q":75,"a":76},"discriminated-union","hard","What is a discriminated union in Pydantic and when is it useful in FastAPI?","A discriminated union uses a `Literal` field as a **type tag** to unambiguously\nselect which model to use during parsing, instead of trying each model in order.\n\n```python\nfrom typing import Literal, Union, Annotated\nfrom pydantic import BaseModel, Field\n\nclass Cat(BaseModel):\n    type: Literal[\"cat\"]\n    meows: bool\n\nclass Dog(BaseModel):\n    type: Literal[\"dog\"]\n    barks: bool\n\nclass PetPayload(BaseModel):\n    pet: Annotated[Union[Cat, Dog], Field(discriminator=\"type\")]\n\npayload = PetPayload.model_validate({\"pet\": {\"type\": \"dog\", \"barks\": True}})\nprint(type(payload.pet))  # \u003Cclass 'Dog'>\n```\n\nDiscriminated unions are:\n- **Faster** — no trial-and-error parsing.\n- **Clearer errors** — \"expected type to be 'cat' or 'dog'\" vs generic failure.\n- **Better OpenAPI** — generates `oneOf` with a discriminator property.\n\nRule of thumb: whenever a body can be one of several shapes, add a `type` tag\nand use a discriminated union — it's explicit, fast, and self-documenting.\n",13,null,{"description":11},"FastAPI Pydantic model interview questions — BaseModel, Field, model_config, nested models, inheritance, computed fields and ORM mode.","fastapi\u002Fpydantic\u002Fmodels","Pydantic Models","Pydantic & Validation","pydantic","2026-06-20","Aj-1OWK5V5w5kHw0JCExAUHqEZCCOYZA0iqfVhNFxzw",[88,89,92,96],{"subtopic":82,"path":21,"order":20},{"subtopic":90,"path":91,"order":12},"Validators","\u002Ffastapi\u002Fpydantic\u002Fvalidation",{"subtopic":93,"path":94,"order":95},"Serialization","\u002Ffastapi\u002Fpydantic\u002Fserialization",3,{"subtopic":97,"path":98,"order":99},"Settings Management","\u002Ffastapi\u002Fpydantic\u002Fsettings",4,1782244112801]