8.17. Model Base

  • Used for reflecting database tables in our program

  • Allows to manage and alter database tables

  • Declarative base (recommended)

  • Imperative (a.k.a. Classical) Mappings

SQLAlchemy historically features two distinct styles of mapper configuration. The original mapping API is commonly referred to as "classical" style, whereas the more automated style of mapping is known as "declarative" style. SQLAlchemy now refers to these two mapping styles as imperative mapping and declarative mapping. Both styles may be used interchangeably, as the end result of each is exactly the same. [1]

base

Model responsible for mapping objects with database

8.17.1. Declarative Base

The Declarative Mapping is the typical way that mappings are constructed in modern SQLAlchemy. The most common pattern is to first construct a base class using the declarative_base() function, which will apply the declarative mapping process to all subclasses that derive from it. Below features a declarative base which is then used in a declarative table mapping [1]:

>>> from sqlalchemy import Column
>>> from sqlalchemy import Integer, String
>>> from sqlalchemy.orm import declarative_base
>>>
>>>
>>> Base = declarative_base()
>>>
>>> class User(Base):
...     __tablename__ = 'user'
...
...     id = Column(Integer, primary_key=True)
...     username = Column(String)
...     password = Column(String)

Above, the declarative_base() callable returns a new base class from which new classes to be mapped may inherit from, as above a new mapped class User is constructed.

8.17.2. Imperative Base

  • Imperative (a.k.a. Classical) Mappings

  • Could be used to map pre-existing classes (od dataclasses) with Table

An imperative or classical mapping refers to the configuration of a mapped class using the registry.map_imperatively() method, where the target class does not include any declarative class attributes. The "map imperative" style has historically been achieved using the mapper() function directly, however this function now expects that a sqlalchemy.orm.registry() is present [1].

>>> from sqlalchemy import Table, Column
>>> from sqlalchemy import Integer, String
>>> from sqlalchemy.orm import registry
>>>
>>>
>>> mapper_registry = registry()
>>>
>>> user_table = Table('user', mapper_registry.metadata,
...     Column('id', Integer, primary_key=True),
...     Column('firstname', String(50)),
...     Column('lastname', String(50)),
... )
>>>
>>> class User:
...     pass
>>>
>>> mapper_registry.map_imperatively(User, user_table)  
<Mapper at 0x...; User>

Information about mapped attributes, such as relationships to other classes, are provided via the properties dictionary.

8.17.3. References