Declarative API

API Reference

Object Name Description

_declarative_constructor(self, **kwargs)

A simple constructor that allows initialization from kwargs.

AbstractConcreteBase

A helper class for ‘concrete’ declarative mappings.

as_declarative(**kw)

Class decorator for declarative_base().

comparable_using(comparator_factory)

Decorator, allow a Python @property to be used in query criteria.

ConcreteBase

A helper class for ‘concrete’ declarative mappings.

declarative_base([bind, metadata, mapper, cls, ...])

Construct a base class for declarative class definitions.

declared_attr

Mark a class-level method as representing the definition of a mapped property or special declarative member name.

DeferredReflection

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

has_inherited_table(cls)

Given a class, return True if any of the classes it inherits from has a mapped table, otherwise return False.

instrument_declarative(cls, registry, metadata)

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

synonym_for(name[, map_column])

Decorator that produces an synonym() attribute in conjunction with a Python descriptor.

function sqlalchemy.ext.declarative.declarative_base(bind=None, metadata=None, mapper=None, cls=<class 'object'>, name='Base', constructor=<function _declarative_constructor>, class_registry=None, metaclass=<class 'sqlalchemy.ext.declarative.api.DeclarativeMeta'>)

Construct a base class for declarative class definitions.

The new base class will be given a metaclass that produces appropriate Table objects and makes the appropriate mapper() calls based on the information provided declaratively in the class and any subclasses of the class.

Parameters:
  • bind – An optional Connectable, will be assigned the bind attribute on the MetaData instance.

  • metadata – An optional MetaData instance. All Table objects implicitly declared by subclasses of the base will share this MetaData. A MetaData instance will be created if none is provided. The MetaData instance will be available via the metadata attribute of the generated declarative base class.

  • mapper – An optional callable, defaults to mapper(). Will be used to map subclasses to their Tables.

  • cls – Defaults to object. A type to use as the base for the generated declarative base class. May be a class or tuple of classes.

  • name – Defaults to Base. The display name for the generated class. Customizing this is not required, but can improve clarity in tracebacks and debugging.

  • constructor – Defaults to _declarative_constructor(), an __init__ implementation that assigns **kwargs for declared fields and relationships to an instance. If None is supplied, no __init__ will be provided and construction will fall back to cls.__init__ by way of the normal Python semantics.

  • class_registry – optional dictionary that will serve as the registry of class names-> mapped classes when string names are used to identify classes inside of relationship() and others. Allows two or more declarative base classes to share the same registry of class names for simplified inter-base relationships.

  • metaclass – Defaults to DeclarativeMeta. A metaclass or __metaclass__ compatible callable to use as the meta type of the generated declarative base class.

Changed in version 1.1: if declarative_base.cls is a single class (rather than a tuple), the constructed base class will inherit its docstring.

See also

as_declarative()

function sqlalchemy.ext.declarative.as_declarative(**kw)

Class decorator for declarative_base().

Provides a syntactical shortcut to the cls argument sent to declarative_base(), allowing the base class to be converted in-place to a “declarative” base:

from sqlalchemy.ext.declarative import as_declarative

@as_declarative()
class Base(object):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id = Column(Integer, primary_key=True)

class MyMappedClass(Base):
    # ...

All keyword arguments passed to as_declarative() are passed along to declarative_base().

class sqlalchemy.ext.declarative.declared_attr(fget, cascading=False)

Mark a class-level method as representing the definition of a mapped property or special declarative member name.

@declared_attr turns the attribute into a scalar-like property that can be invoked from the uninstantiated class. Declarative treats attributes specifically marked with @declared_attr as returning a construct that is specific to mapping or declarative table configuration. The name of the attribute is that of what the non-dynamic version of the attribute would be.

@declared_attr is more often than not applicable to mixins, to define relationships that are to be applied to different implementors of the class:

class ProvidesUser(object):
    "A mixin that adds a 'user' relationship to classes."

    @declared_attr
    def user(self):
        return relationship("User")

It also can be applied to mapped classes, such as to provide a “polymorphic” scheme for inheritance:

class Employee(Base):
    id = Column(Integer, primary_key=True)
    type = Column(String(50), nullable=False)

    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    @declared_attr
    def __mapper_args__(cls):
        if cls.__name__ == 'Employee':
            return {
                    "polymorphic_on":cls.type,
                    "polymorphic_identity":"Employee"
            }
        else:
            return {"polymorphic_identity":cls.__name__}

Members

cascading

Class signature

class sqlalchemy.ext.declarative.declared_attr (sqlalchemy.orm.base._MappedAttribute, builtins.property)

attribute sqlalchemy.ext.declarative.declared_attr.cascading

Mark a declared_attr as cascading.

This is a special-use modifier which indicates that a column or MapperProperty-based declared attribute should be configured distinctly per mapped subclass, within a mapped-inheritance scenario.

Warning

The declared_attr.cascading modifier has several limitations:

  • The flag only applies to the use of declared_attr on declarative mixin classes and __abstract__ classes; it currently has no effect when used on a mapped class directly.

  • The flag only applies to normally-named attributes, e.g. not any special underscore attributes such as __tablename__. On these attributes it has no effect.

  • The flag currently does not allow further overrides down the class hierarchy; if a subclass tries to override the attribute, a warning is emitted and the overridden attribute is skipped. This is a limitation that it is hoped will be resolved at some point.

Below, both MyClass as well as MySubClass will have a distinct id Column object established:

class HasIdMixin(object):
    @declared_attr.cascading
    def id(cls):
        if has_inherited_table(cls):
            return Column(
                ForeignKey('myclass.id'), primary_key=True
            )
        else:
            return Column(Integer, primary_key=True)

class MyClass(HasIdMixin, Base):
    __tablename__ = 'myclass'
    # ...

class MySubClass(MyClass):
    ""
    # ...

The behavior of the above configuration is that MySubClass will refer to both its own id column as well as that of MyClass underneath the attribute named some_id.

function sqlalchemy.ext.declarative.api._declarative_constructor(self, **kwargs)

A simple constructor that allows initialization from kwargs.

Sets attributes on the constructed instance using the names and values in kwargs.

Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.

function sqlalchemy.ext.declarative.has_inherited_table(cls)

Given a class, return True if any of the classes it inherits from has a mapped table, otherwise return False.

This is used in declarative mixins to build attributes that behave differently for the base class vs. a subclass in an inheritance hierarchy.

function sqlalchemy.ext.declarative.synonym_for(name, map_column=False)

Decorator that produces an synonym() attribute in conjunction with a Python descriptor.

The function being decorated is passed to synonym() as the synonym.descriptor parameter:

class MyClass(Base):
    __tablename__ = 'my_table'

    id = Column(Integer, primary_key=True)
    _job_status = Column("job_status", String(50))

    @synonym_for("job_status")
    @property
    def job_status(self):
        return "Status: %s" % self._job_status

The hybrid properties feature of SQLAlchemy is typically preferred instead of synonyms, which is a more legacy feature.

See also

Synonyms - Overview of synonyms

synonym() - the mapper-level function

Using Descriptors and Hybrids - The Hybrid Attribute extension provides an updated approach to augmenting attribute behavior more flexibly than can be achieved with synonyms.

function sqlalchemy.ext.declarative.comparable_using(comparator_factory)

Decorator, allow a Python @property to be used in query criteria.

This is a decorator front end to comparable_property() that passes through the comparator_factory and the function being decorated:

@comparable_using(MyComparatorType)
@property
def prop(self):
    return 'special sauce'

The regular comparable_property() is also usable directly in a declarative setting and may be convenient for read/write properties:

prop = comparable_property(MyComparatorType)
function sqlalchemy.ext.declarative.instrument_declarative(cls, registry, metadata)

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

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 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:

Members

prepare()

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

Reflect all Table objects for all current DeferredReflection subclasses

Special Directives

__declare_last__()

The __declare_last__() hook allows definition of a class level function that is automatically called by the MapperEvents.after_configured() event, which occurs after mappings are assumed to be completed and the ‘configure’ step has finished:

class MyClass(Base):
    @classmethod
    def __declare_last__(cls):
        ""
        # do something with mappings

__declare_first__()

Like __declare_last__(), but is called at the beginning of mapper configuration via the MapperEvents.before_configured() event:

class MyClass(Base):
    @classmethod
    def __declare_first__(cls):
        ""
        # do something before mappings are configured

New in version 0.9.3.

__abstract__

__abstract__ causes declarative to skip the production of a table or mapper for the class entirely. A class can be added within a hierarchy in the same way as mixin (see Mixin and Custom Base Classes), allowing subclasses to extend just from the special class:

class SomeAbstractBase(Base):
    __abstract__ = True

    def some_helpful_method(self):
        ""

    @declared_attr
    def __mapper_args__(cls):
        return {"helpful mapper arguments":True}

class MyMappedClass(SomeAbstractBase):
    ""

One possible use of __abstract__ is to use a distinct MetaData for different bases:

Base = declarative_base()

class DefaultBase(Base):
    __abstract__ = True
    metadata = MetaData()

class OtherBase(Base):
    __abstract__ = True
    metadata = MetaData()

Above, classes which inherit from DefaultBase will use one MetaData as the registry of tables, and those which inherit from OtherBase will use a different one. The tables themselves can then be created perhaps within distinct databases:

DefaultBase.metadata.create_all(some_engine)
OtherBase.metadata.create_all(some_other_engine)

__table_cls__

Allows the callable / class used to generate a Table to be customized. This is a very open-ended hook that can allow special customizations to a Table that one generates here:

class MyMixin(object):
    @classmethod
    def __table_cls__(cls, name, metadata, *arg, **kw):
        return Table(
            "my_" + name,
            metadata, *arg, **kw
        )

The above mixin would cause all Table objects generated to include the prefix "my_", followed by the name normally specified using the __tablename__ attribute.

__table_cls__ also supports the case of returning None, which causes the class to be considered as single-table inheritance vs. its subclass. This may be useful in some customization schemes to determine that single-table inheritance should take place based on the arguments for the table itself, such as, define as single-inheritance if there is no primary key present:

class AutoTable(object):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__

    @classmethod
    def __table_cls__(cls, *arg, **kw):
        for obj in arg[1:]:
            if (isinstance(obj, Column) and obj.primary_key) or \
                    isinstance(obj, PrimaryKeyConstraint):
                return Table(*arg, **kw)

        return None

class Person(AutoTable, Base):
    id = Column(Integer, primary_key=True)

class Employee(Person):
    employee_name = Column(String)

The above Employee class would be mapped as single-table inheritance against Person; the employee_name column would be added as a member of the Person table.

New in version 1.0.0.