Stage 3 · L07
Understand Pydantic types, conversion and validation
Core · original Session 3
Pydantic validates data at a boundary and produces typed values. EquipmentIn accepts a name, integer quantity and Decimal daily_rate. quantity='3' converts to integer 3 in the default policy; quantity='three' cannot convert and raises validation error. Conversion is deliberate behavior, not proof that clients originally sent the correct JSON type.
Constraints are separate from types. An integer quantity of zero has the right Python type but violates ge=1. A rate of 12.505 violates decimal_places=2. An empty name violates min_length. extra='forbid' rejects hidden keys such as role. These request errors occur before the handler creates a database row; the baseline checks a fresh row count after every rejected payload.
Required and nullable describe different things. nickname: str | None permits null but remains required without a default. nickname: str | None = None permits omission too. The scoped test uses the first form and confirms that omission fails. For a future PATCH, model_dump(exclude_unset=True) preserves omission; an explicitly supplied null remains supplied and needs a domain decision.
Field(strict=True) on an integer rejects a numeric string that default conversion would accept. Use strictness where the contract needs it, and test that boundary. Strictness does not replace business rules, foreign keys or a transaction. Pydantic is not permission checking, email deliverability, stock enforcement or SQL injection protection.
Errors include locations and kinds so a client can identify the invalid field. Do not echo credential values or raw database exceptions in an API error. FastAPI maps request validation to 422 for these routes. A valid request can still encounter a uniqueness conflict at PostgreSQL; that later failure is 409 and must leave no partial write.
Follow the running code
Focused lesson example; see the end-of-stage capstone for the cumulative app · stage 03
from pydantic import BaseModel, ConfigDict, Field
class QuantityIn(BaseModel):
model_config = ConfigDict(extra='forbid')
quantity: int = Field(ge=1)
note: str | None # Nullable, but still required without a default.
valid = QuantityIn(quantity='2', note=None)
assert valid.quantity == 2Predict and observe this focused example using the concepts explained above. Its boundary is stated in the focused answer.
Guided lab
- Read the explanation and predict the focused example’s outcome.
- Predict quantity='2', quantity=0, missing note and an extra role field. How would strict=True change numeric-string acceptance?
- Compare the observed outcome with the focused answer and state its boundary.
Expected: The non-strict integer accepts '2'; zero violates the bound; note may be None but omission is invalid because it has no default; role is an extra forbidden key. Field(strict=True) rejects the numeric string. None of these schema checks reserves stock or commits a database row.
- Validation succeeds before a uniqueness conflict; it cannot guarantee a later database commit.
Focused exercise and answer
Complete this focused exercise before reading its answer. The full native transfer is introduced only at the end of the stage.
Your transfer task: Predict quantity='2', quantity=0, missing note and an extra role field. How would strict=True change numeric-string acceptance?
- Predict quantity='2', quantity=0, missing note and an extra role field. How would strict=True change numeric-string acceptance?
Inspect the matching answer
This answer addresses the focused exercise above; the cumulative implementation is shown only after the stage prerequisites.
The non-strict integer accepts '2'; zero violates the bound; note may be None but omission is invalid because it has no default; role is an extra forbidden key. Field(strict=True) rejects the numeric string. None of these schema checks reserves stock or commits a database row.Check your reasoning
Does str | None mean a field may be omitted?
Show the explanation
Only if a default is supplied. Nullable permits null; required controls presence.
Reading progress
54 lessons remain open to guests. Marking a lesson read records reading only; it does not award assessment credit or a certificate.
Device reading marks require browser storage. Reading is always available.
Sign in or create an account to save separate account progress. Your current page is kept.
Your earlier place on this device suggests these lessons. No new lesson is marked read.