Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

声明性扩展

特定于 Declarative 映射API。

在 1.4 版更改: 绝大多数声明性扩展现在集成到SQLAlchemy ORM中,并且可以从 sqlalchemy.orm 命名空间。请参阅上的文档 声明性映射 对于新文档。有关更改的概述,请参见 声明式现在集成到ORM中,具有新的特性 .

Object Name Description

AbstractConcreteBase

“concrete”声明性映射的助手类。

ConcreteBase

“concrete”声明性映射的助手类。

DeferredReflection

用于基于延迟反射步骤构造映射的助手类。

class sqlalchemy.ext.declarative.AbstractConcreteBase

“concrete”声明性映射的助手类。

AbstractConcreteBase 将使用 polymorphic_union() 自动对作为子类映射到此类的所有表执行函数。函数通过调用 __declare_last__() 函数,它本质上是 after_configured() 事件。

AbstractConcreteBase 不会为基类生成一个映射类,但是它不会持久化到任何表;而是直接映射到可直接选择的“多态”类,并且只用于选择。比较 ConcreteBase ,它确实为基类创建了持久化表。

注解

这个 AbstractConcreteBase 类不打算为基类设置映射,除非定义了所有子类,因为它需要针对包含所有子类表的可选对象创建映射。为了实现这一点,它等待 映射器配置事件 此时,它会扫描所有已配置的子类,并设置一个映射,该映射将同时查询所有子类。

当此事件通常自动调用时, AbstractConcreteBase ,可能需要在 all 如果第一个操作是对这个基类的查询,则定义子类映射。为此,调用 configure_mappers() 配置完所有所需的类后:

from sqlalchemy.orm import configure_mappers

configure_mappers()

例子::

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()

抽象基类是由声明性的以特殊方式处理的;在类配置时,它的行为类似于声明性混合或 __abstract__ 基类。一旦配置了类并生成了映射,它就会自己被映射,但在它的所有后代之后。这是一个非常独特的映射系统,在任何其他sqlacalchemy系统中都找不到。

使用这种方法,我们可以指定将在映射的子类上发生的列和属性,就像我们通常在 混合和自定义基类 ::

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()

然而,当我们使用我们的映射时,两者都 ManagerEmployee 将具有独立可用的 .company 属性:

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

在 1.0.0 版更改: -力学 AbstractConcreteBase 已经被改写以支持直接建立在抽象基础上的关系,而没有任何特殊的构型步骤。

class sqlalchemy.ext.declarative.ConcreteBase

“concrete”声明性映射的助手类。

ConcreteBase 将使用 polymorphic_union() 自动对作为子类映射到此类的所有表执行函数。函数通过调用 __declare_last__() 函数,它本质上是 after_configured() 事件。

ConcreteBase 为类本身生成映射表。比较 AbstractConcreteBase 但事实并非如此。

例子::

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}

使用的鉴别器列的名称 polymorphic_union() 默认为名称 type . 已将一个名为suit的列映射到case中 type ,可以通过设置 _concrete_discriminator_name 属性:

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

1.3.19 新版功能: 增加了 _concrete_discriminator_name 属性到 ConcreteBase 以便可以自定义虚拟鉴别器列名。

在 1.4.2 版更改: 这个 _concrete_discriminator_name 属性只需放在基类上即可对所有子类产生正确效果。现在,如果映射的列名与鉴别器名称冲突,则会引发一条显式错误消息,而在1.3.x系列中会出现一些警告,然后会生成一个无用的查询。

class sqlalchemy.ext.declarative.DeferredReflection

用于基于延迟反射步骤构造映射的助手类。

通常,声明性可以与反射一起使用,方法是将 Table 使用autoload_with=engine作为 __table__ 属性添加到声明性类上。需要注意的是, Table 必须在构造普通声明性映射时完全反映,或者至少有一个主键列,这意味着 Engine 必须在类声明时可用。

这个 DeferredReflection mixin将映射器的构造移动到后面的某个点,在调用一个首先反映所有 Table 到目前为止创建的对象。类可以这样定义它:

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

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

上面, MyClass 尚未映射。在以上述方式定义了一系列类之后,可以使用 prepare() ::

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

这个 DeferredReflection mixin可以应用于单个类,用作声明性基本身的基,或者用于自定义抽象类。使用抽象基只允许为特定的准备步骤准备类的子集,这对于使用多个引擎的应用程序是必需的。例如,如果一个应用程序有两个引擎,您可以使用两个基,并分别准备每个基,例如:

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.

上面的类层次结构 ReflectedOneReflectedTwo 可单独配置:

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

反映一切 Table 所有当前对象 DeferredReflection 子类

Previous: 烘焙查询 Next: 声明性API