Skip to content
Aabha AI Academy

Stage 2 · L14

Separate ORM models, API schemas and schema migrations

Core · original Session 2; extended normalization/cardinality visuals

An ORM model declares how Python objects map to stored tables. A Pydantic schema declares an API input/output contract. A migration declares a reviewed change to the database schema. They can describe related facts without having identical fields or lifetimes. Editing a model does not change an already created PostgreSQL table.

Import order matters. Declarative classes register their tables in Base.metadata when their modules execute. migrations/env.py imports equipment.models before reading Base.metadata so Equipment, User and Rental are registered. Importing an empty Base from another module without importing model declarations can produce empty metadata and a misleading migration. Inspect the table set before generating changes.

Run Alembic upgrade head against a new disposable database. It creates the three tables and records revision 0001 in alembic_version. Running it again should leave the same revision applied. Application startup does not call create_all or silently alter columns. The migration is a separate intentional setup step; /health/ready's SELECT 1 does not prove revision 0001 exists.

The original Session 02 uses a simple table-creation path to introduce persistence. This revision keeps the existing Aabha migration discipline and explains the distinction: create_all creates missing tables but is not a schema-evolution plan for existing columns. Do not teach changing a model and restarting as if it were an upgrade.

Future state/capacity/data-evolution lessons will introduce a new forward migration with a data strategy. This initial checkpoint refuses destructive downgrade rather than deleting learner data automatically. For the guided exercise, change a model only in a temporary working copy, inspect the unchanged live table with SQLAlchemy's inspector, then revert the code. The baseline confirms the migrated table set, not arbitrary future migrations.

ORM model: Python ↔ stored row; Pydantic: input/output boundary; Migration: reviewed schema change; Alembic 0001: creates three tables; Editing a model does not update an; existing table.
ORM model: Python ↔ stored row; Pydantic: input/output boundary; Migration: reviewed schema change; Alembic 0001: creates three tables; Editing a model does not update an; existing table.

Follow the running code

Focused lesson example; see the end-of-stage capstone for the cumulative app · stage 02

python -m alembic current
python -m alembic upgrade head
python -m alembic current
# Model edits do not execute these commands automatically.

Predict and observe this focused example using the concepts explained above. Its boundary is stated in the focused answer.

Guided lab

  1. Read the explanation and predict the focused example’s outcome.
  2. Explain what importing a model, declaring a Pydantic schema and running a forward migration each changes.
  3. Compare the observed outcome with the focused answer and state its boundary.

Expected: Importing a SQLAlchemy model registers its mapping/table metadata in Python. Pydantic defines accepted/public values, not database storage. Alembic executes a reviewed schema revision against the selected database and records its version. create_all can create missing tables but is not an existing-table evolution plan.

  • Model-only new columns cause queries to fail against old tables; metadata missing model imports can omit tables.

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: Explain what importing a model, declaring a Pydantic schema and running a forward migration each changes.

  1. Explain what importing a model, declaring a Pydantic schema and running a forward migration each changes.
Inspect the matching answer

This answer addresses the focused exercise above; the cumulative implementation is shown only after the stage prerequisites.

Importing a SQLAlchemy model registers its mapping/table metadata in Python. Pydantic defines accepted/public values, not database storage. Alembic executes a reviewed schema revision against the selected database and records its version. create_all can create missing tables but is not an existing-table evolution plan.

Check your reasoning

What operation changes an existing column definition safely?

Show the explanation

A reviewed forward migration with a data/compatibility plan, not editing the model or calling create_all.

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.