Release: 1.4.0b1 pre release | Release Date: unreleased

SQLAlchemy 1.4 Documentation

Declarative API

API Reference

Changed in version 1.4: The fundamental structures of the declarative system are now part of SQLAlchemy ORM directly. For these components see:

Object Name Description

AbstractConcreteBase

A helper class for ‘concrete’ declarative mappings.

ConcreteBase

A helper class for ‘concrete’ declarative mappings.

DeferredReflection

A helper class for construction of mappings based on a deferred reflection step.

instrument_declarative(cls, cls_registry, metadata)

Given a class, configure the class declaratively, using the given registry, which can be any dictionary, and MetaData object.

function sqlalchemy.ext.declarative.instrument_declarative(cls, cls_registry, metadata)

Given a class, configure the class declaratively, using the given registry, which can be any dictionary, and MetaData object.

Deprecated since version 1.4: the instrument_declarative function is deprecated and will be removed in SQLAlhcemy 2.0. Please use map_declaratively (Background on SQLAlchemy 2.0 at: :ref:`migration_20_toplevel())

class sqlalchemy.ext.declarative.AbstractConcreteBase

A helper class for ‘concrete’ declarative mappings.

AbstractConcreteBase will use the polymorphic_union() function automatically, against all tables mapped as a subclass to this class. The function is called via the __declare_last__() function, which is essentially a hook for the after_configured() event.

AbstractConcreteBase does produce a mapped class for the base class, however it is not persisted to any table; it is instead mapped directly to the “polymorphic” selectable directly and is only used for selecting. Compare to ConcreteBase, which does create a persisted table for the base class.

Note

The AbstractConcreteBase class does not intend to set up the mapping for the base class until all the subclasses have been defined, as it needs to create a mapping against a selectable that will include all subclass tables. In order to achieve this, it waits for the mapper configuration event to occur, at which point it scans through all the configured subclasses and sets up a mapping that will query against all subclasses at once.

While this event is normally invoked automatically, in the case of AbstractConcreteBase, it may be necessary to invoke it explicitly after all subclass mappings are defined, if the first operation is to be a query against this base class. To do so, invoke configure_mappers() once all the desired classes have been configured:

from sqlalchemy.orm import configure_mappers

configure_mappers()

Example:

from sqlalchemy.ext.declarative import AbstractConcreteBase

class Employee(AbstractConcreteBase, Base):
    pass

class Manager(Employee):
    __tablename__ = 'manager'
    employee_id = Column(Integer, primary_key=True)
    name = Column(String(50))
    manager_data = Column(String(40))

    __mapper_args__ = {
        'polymorphic_identity':'manager',
        'concrete':True}

configure_mappers()

The abstract base class is handled by declarative in a special way; at class configuration time, it behaves like a declarative mixin or an __abstract__ base class. Once classes are configured and mappings are produced, it then gets mapped itself, but after all of its descendants. This is a very unique system of mapping not found in any other SQLAlchemy system.

Using this approach, we can specify columns and properties that will take place on mapped subclasses, in the way that we normally do as in Mixin and Custom Base Classes:

class Company(Base):
    __tablename__ = 'company'
    id = Column(Integer, primary_key=True)

class Employee(AbstractConcreteBase, Base):
    employee_id = Column(Integer, primary_key=True)

    @declared_attr
    def company_id(cls):
        return Column(ForeignKey('company.id'))

    @declared_attr
    def company(cls):
        return relationship("Company")

class Manager(Employee):
    __tablename__ = 'manager'

    name = Column(String(50))
    manager_data = Column(String(40))

    __mapper_args__ = {
        'polymorphic_identity':'manager',
        'concrete':True}

configure_mappers()

When we make use of our mappings however, both Manager and Employee will have an independently usable .company attribute:

session.query(Employee).filter(Employee.company.has(id=5))

Changed in version 1.0.0: - The mechanics of AbstractConcreteBase have been reworked to support relationships established directly on the abstract base, without any special configurational steps.

Class signature

class sqlalchemy.ext.declarative.AbstractConcreteBase (sqlalchemy.ext.declarative.extensions.ConcreteBase)

class sqlalchemy.ext.declarative.ConcreteBase

A helper class for ‘concrete’ declarative mappings.

ConcreteBase will use the polymorphic_union() function automatically, against all tables mapped as a subclass to this class. The function is called via the __declare_last__() function, which is essentially a hook for the after_configured() event.

ConcreteBase produces a mapped table for the class itself. Compare to AbstractConcreteBase, which does not.

Example:

from sqlalchemy.ext.declarative import ConcreteBase

class Employee(ConcreteBase, Base):
    __tablename__ = 'employee'
    employee_id = Column(Integer, primary_key=True)
    name = Column(String(50))
    __mapper_args__ = {
                    'polymorphic_identity':'employee',
                    'concrete':True}

class Manager(Employee):
    __tablename__ = 'manager'
    employee_id = Column(Integer, primary_key=True)
    name = Column(String(50))
    manager_data = Column(String(40))
    __mapper_args__ = {
                    'polymorphic_identity':'manager',
                    'concrete':True}

The name of the discriminator column used by polymorphic_union() defaults to the name type. To suit the use case of a mapping where an actual column in a mapped table is already named type, the discriminator name can be configured by setting the _concrete_discriminator_name attribute:

class Employee(ConcreteBase, Base):
    _concrete_discriminator_name = '_concrete_discriminator'

New in version 1.3.19: Added the _concrete_discriminator_name attribute to ConcreteBase so that the virtual discriminator column name can be customized.

class sqlalchemy.ext.declarative.DeferredReflection

A helper class for construction of mappings based on a deferred reflection step.

Normally, declarative can be used with reflection by setting a Table object using autoload=True as the __table__ attribute on a declarative class. The caveat is that the Table must be fully reflected, or at the very least have a primary key column, at the point at which a normal declarative mapping is constructed, meaning the Engine must be available at class declaration time.

The DeferredReflection mixin moves the construction of mappers to be at a later point, after a specific method is called which first reflects all Table objects created so far. Classes can define it as such:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import DeferredReflection
Base = declarative_base()

class MyClass(DeferredReflection, Base):
    __tablename__ = 'mytable'

Above, MyClass is not yet mapped. After a series of classes have been defined in the above fashion, all tables can be reflected and mappings created using prepare():

engine = create_engine("someengine://...")
DeferredReflection.prepare(engine)

The DeferredReflection mixin can be applied to individual classes, used as the base for the declarative base itself, or used in a custom abstract class. Using an abstract base allows that only a subset of classes to be prepared for a particular prepare step, which is necessary for applications that use more than one engine. For example, if an application has two engines, you might use two bases, and prepare each separately, e.g.:

class ReflectedOne(DeferredReflection, Base):
    __abstract__ = True

class ReflectedTwo(DeferredReflection, Base):
    __abstract__ = True

class MyClass(ReflectedOne):
    __tablename__ = 'mytable'

class MyOtherClass(ReflectedOne):
    __tablename__ = 'myothertable'

class YetAnotherClass(ReflectedTwo):
    __tablename__ = 'yetanothertable'

# ... etc.

Above, the class hierarchies for ReflectedOne and ReflectedTwo can be configured separately:

ReflectedOne.prepare(engine_one)
ReflectedTwo.prepare(engine_two)
method sqlalchemy.ext.declarative.DeferredReflection.classmethod prepare(engine)

Reflect all Table objects for all current DeferredReflection subclasses