0Pricing
Python Academy · Lesson

Defining Models

Map classes to tables.

Defining Models is a free Python Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Models Map to Tables

In the SQLAlchemy ORM, a model is a Python class that maps to a database table. Each instance becomes a row.

Models inherit from a shared Base class.

from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
    pass
print('Base class ready')

The __tablename__

Every model sets __tablename__ to name its table. SQLAlchemy uses this when generating SQL.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
print(User.__tablename__)

Columns with Mapped

Modern SQLAlchemy declares columns with type hints: Mapped[int] and mapped_column(). The type hint sets the Python type and informs the column type.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    age: Mapped[int]
print('User has id, name, age')

The Primary Key

Mark a column as the primary key with primary_key=True. Integer primary keys auto-increment by default.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class Product(Base):
    __tablename__ = 'products'
    id: Mapped[int] = mapped_column(primary_key=True)
    title: Mapped[str]
print('id is the primary key')

Optional Columns

Use Mapped[str | None] or Optional[str] to allow NULL values. A plain Mapped[str] is NOT NULL.

from typing import Optional
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    nickname: Mapped[Optional[str]]
print('nickname can be NULL')

Defaults and Uniqueness

mapped_column() takes options like unique=True and default= to add constraints and fallback values.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(unique=True)
    active: Mapped[bool] = mapped_column(default=True)
print('email is unique, active defaults to True')

String Length

For databases that need it, set a string length with mapped_column(String(50)).

from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(50))
print('name limited to 50 chars')

Creating the Schema

Base.metadata.create_all(engine) creates tables for every model that inherits from Base.

from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
print('Schema created')

Creating Instances

Build a row by instantiating the model like a normal Python object, passing column values as keyword arguments.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
u = User(name='Alice')
print(u.name)

Adding a __repr__

A custom __repr__ makes debugging easier by showing the object's data clearly.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    def __repr__(self):
        return 'User(name=' + self.name + ')'
print(repr(User(name='Bob')))

Models Stay Plain Python

A model is still an ordinary class. You can add methods and properties that operate on its data, mixing behavior with persistence.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    pass
class User(Base):
    __tablename__ = 'users'
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    def greet(self):
        return 'Hi, ' + self.name
print(User(name='Carol').greet())

Quick Check

Test your model-definition skills.

Recap

You learned to define ORM models.

  • Models inherit from a DeclarativeBase and set __tablename__
  • Columns use Mapped[type] and mapped_column()
  • primary_key, unique, and default add constraints
  • create_all() builds the tables

Frequently asked questions

Is the “Defining Models” lesson free?

Yes — the full text of “Defining Models” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.

What will I learn in “Defining Models”?

Map classes to tables. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Python Academy?

No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Defining Models” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Python Academy lesson?

Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. SQLAlchemy Core vs ORM
  2. Defining Models
  3. Querying with the Session
  4. Relationships and Joins
← Back to Python Academy