Extensions specific to the Declarative mapping API.
Changed in version 1.4: The vast majority of the Declarative extension is now
integrated into the SQLAlchemy ORM and is importable from the
sqlalchemy.orm
namespace. See the documentation at
Declarative Mapping for new documentation.
For an overview of the change, see Declarative is now integrated into the ORM with new features.
Object Name | Description |
---|---|
A helper class for ‘concrete’ declarative mappings. |
|
A helper class for ‘concrete’ declarative mappings. |
|
A helper class for construction of mappings based on a deferred reflection step. |
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()
See also
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
)
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.
Changed in version 1.4.2: The _concrete_discriminator_name
attribute
need only be placed on the basemost class to take correct effect for
all subclasses. An explicit error message is now raised if the
mapped column names conflict with the discriminator name, whereas
in the 1.3.x series there would be some warnings and then a non-useful
query would be generated.
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_with=engine
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)
sqlalchemy.ext.declarative.DeferredReflection.
classmethod prepare
(engine)¶Reflect all Table
objects for all current
DeferredReflection
subclasses
flambé! the dragon and The Alchemist image designs created and generously donated by Rotem Yaari.
Created using Sphinx 3.5.3.