正如在 声明性映射 ,声明式样式包括生成映射 Table
对象,或容纳 Table
或其他 FromClause
直接对象。
以下示例假定声明性基类为:
from sqlalchemy.orm import declarative_base
Base = declarative_base()
下面的所有示例都说明了从上面继承的类 Base
. 装饰风格 使用修饰符的声明性映射(无声明基) 下面的所有示例也完全支持。
对于声明性基类,典型的映射形式包括一个属性 __tablename__
它指示一个 Table
应该与映射一起生成:
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
nickname = Column(String)
上面, Column
对象与类定义内联放置。声明性映射过程将生成一个新的 Table
反对 MetaData
与声明基关联的集合,并且每个 Column
对象将成为 Table.columns
这个的集合 Table
对象。这个 Column
对象可以省略其“name”字段,该字段通常是 Column
构造函数;声明性系统将分配与每个 Column
作为名字,产生一个 Table
相当于:
# equivalent Table object produced
user_table = Table(
"user",
Base.metadata,
Column("id", Integer, primary_key=True),
Column("name", String),
Column("fullname", String),
Column("nickname", String),
)
声明性映射类将始终包含一个名为 __table__
;当上述配置使用 __tablename__
完成时,声明过程使 Table
可通过 __table__
属性:
# access the Table
user_table = User.__table__
上表与 Mapper.local_table
属性,我们可以通过 runtime inspection system ::
from sqlalchemy import inspect
user_table = inspect(User).local_table
这个 MetaData
与声明性 registry
以及基类通常是运行DDL操作(如CREATE)以及与迁移工具(如Alembic)一起使用时所必需的。此对象可通过 .metadata
属性 registry
以及声明性基类。下面,对于一个小脚本,我们可能希望针对SQLite数据库发出一个CREATE for all tables::
engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
使用声明性表配置时 __tablename__
声明类属性,要提供给 Table
构造函数应该使用 __table_args__
声明类属性。
此属性包含通常发送到的位置参数和关键字参数 Table
构造函数。属性可以用两种形式之一指定。一本是字典:
class MyClass(Base):
__tablename__ = 'sometable'
__table_args__ = {'mysql_engine':'InnoDB'}
另一个是元组,其中每个参数都是位置的(通常是约束)::
class MyClass(Base):
__tablename__ = 'sometable'
__table_args__ = (
ForeignKeyConstraint(['id'], ['remote_table.id']),
UniqueConstraint('foo'),
)
通过将最后一个参数指定为字典,可以使用上述表单指定关键字参数::
class MyClass(Base):
__tablename__ = 'sometable'
__table_args__ = (
ForeignKeyConstraint(['id'], ['remote_table.id']),
UniqueConstraint('foo'),
{'autoload':True}
)
类也可以指定 __table_args__
声明性属性,以及 __tablename__
属性,在动态样式中使用 declared_attr()
方法装饰器。参见章节 混合和自定义基类 举例说明如何经常使用。
的架构名称 Table
如文件所示 指定架构名称 适用于个人 Table
使用 Table.schema
争论。使用声明性表时,此选项与其他选项一样传递给 __table_args__
字典:
class MyClass(Base):
__tablename__ = 'sometable'
__table_args__ = {'schema': 'some_schema'}
架构名称也可以应用于所有 Table
通过使用 MetaData.schema
参数记录在 使用元数据指定默认架构名称 . 这个 MetaData
对象可以单独构造并传递给 registry()
或 declarative_base()
::
from sqlalchemy import MetaData
metadata_obj = MetaData(schema="some_schema")
Base = declarative_base(metadata = metadata_obj)
class MyClass(Base):
# will use "some_schema" by default
__tablename__ = 'sometable'
声明性表配置允许添加新的 Column
两种情况下的对象。最基本的是简单地分配新的 Column
类的对象:
MyClass.some_new_column = Column('data', Unicode)
对使用声明性基(注意,不是声明性的decorator形式)映射的声明性类执行的上述操作将添加上述内容 Column
到 Table
使用 Table.append_column()
方法,并将列添加到 Mapper
完全映射。
注解
将新列分配给现有的声明性映射类只有在使用“声明性基”类时才能正常工作,这也提供了元类驱动 __setattr__()
方法来截获这些操作。会的 not 如果 registry.mapped()
它也不适用于由映射的强制映射类 registry.map_imperatively()
.
另一种情况是 Column
动态添加是指没有自己表的继承子类指示其他列;这些列将被添加到超类表中。部门 单表继承 讨论单表继承。
声明性映射也可以与预先存在的 Table
对象,或 Table
或者其他武断的 FromClause
构造(例如 Join
或 Subquery
)它是分开建造的。
这被称为“混合声明性”映射,因为类是使用声明式样式映射涉及映射器配置的所有内容,但是映射 Table
对象单独生成并直接传递给声明性进程:
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey
Base = declarative_base()
# construct a Table directly. The Base.metadata collection is
# usually a good choice for MetaData but any MetaData
# collection may be used.
user_table = Table(
"user",
Base.metadata,
Column("id", Integer, primary_key=True),
Column("name", String),
Column("fullname", String),
Column("nickname", String),
)
# construct the User class using this table.
class User(Base):
__table__ = user_table
以上,A Table
对象是使用中描述的方法构造的 用元数据描述数据库 . 然后可以直接将其应用于声明性映射的类。这个 __tablename__
和 __table_args__
此表单中未使用声明性类属性。作为内联定义,上述配置通常更具可读性:
class User(Base):
__table__ = Table(
"user",
Base.metadata,
Column("id", Integer, primary_key=True),
Column("name", String),
Column("fullname", String),
Column("nickname", String),
)
上述风格的自然效果是 __table__
属性本身在类定义块中定义。因此,可以在随后的属性中立即引用它,例如下面的示例说明了对 type
多态映射器配置中的列::
class Person(Base):
__table__ = Table(
'person',
Base.metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('type', String(50))
)
__mapper_args__ = {
"polymorphic_on": __table__.c.type,
"polymorhpic_identity": "person"
}
当非 -Table
构造,例如 Join
或 Subquery
对象,将被映射。下面是一个例子:
from sqlalchemy import select, func
subq = select(
func.count(orders.c.id).label('order_count'),
func.max(orders.c.price).label('highest_order'),
orders.c.customer_id
).group_by(orders.c.customer_id).subquery()
customer_select = select(customers, subq).join_from(
customers, subq, customers.c.id == subq.c.customer_id
).subquery()
class Customer(Base):
__table__ = customer_select
关于映射到非 -Table
构件见截面 根据多个表映射类 和 针对任意子查询映射类 .
当类本身使用属性声明的替代形式(如Python数据类)时,“命令表”形式特别有用。参见章节 具有数据类和属性的声明性映射 细节。
有几种可用的模式提供了针对一系列 Table
使用中描述的反射过程从数据库中内省的对象 反映数据库对象 .
将类映射到从数据库反映的表的一种非常简单的方法是使用声明性混合映射,传递 Table.autoload_with
参数 Table
::
engine = create_engine("postgresql://user:pass@hostname/my_existing_database")
class MyClass(Base):
__table__ = Table(
'mytable',
Base.metadata,
autoload_with=engine
)
然而,上述方法的一个主要缺点是,它要求在声明应用程序类时存在数据库连接源;通常情况下,类声明为应用程序的模块被导入,但是数据库连接在应用程序开始运行代码之前是不可用的,这样它就可以使用配置信息并创建引擎。
为了适应这种情况,一个名为 DeferredReflection
mixin是可用的,它将声明性映射过程延迟到一个特殊的类级别 DeferredReflection.prepare()
方法,该方法将对目标数据库执行反射过程,并将结果与声明性表映射过程(即使用 __tablename__
属性:
from sqlalchemy.orm import declarative_base
from sqlalchemy.ext.declarative import DeferredReflection
Base = declarative_base()
class Reflected(DeferredReflection):
__abstract__ = True
class Foo(Reflected, Base):
__tablename__ = 'foo'
bars = relationship("Bar")
class Bar(Reflected, Base):
__tablename__ = 'bar'
foo_id = Column(Integer, ForeignKey('foo.id'))
上面,我们创建了一个mixin类 Reflected
它将作为声明性层次结构中的类的基,当 Reflected.prepare
方法被调用。在我们这样做之前,上面的映射是不完整的 Engine
::
engine = create_engine("postgresql://user:pass@hostname/my_existing_database")
Reflected.prepare(engine)
目的 Reflected
类定义类的反射映射范围。插件将在目标的子类树中搜索 .prepare()
调用并反映所有表。
针对要使用表反射的现有数据库进行映射的更自动化的解决方案是使用 自动程序 扩展。这个扩展将从数据库模式生成完整的映射类,并允许几个钩子进行自定义,包括显式映射某些或所有类,同时仍然使用反射来填充其余列。
参见
flambé! the dragon and The Alchemist image designs created and generously donated by Rotem Yaari.
Created using Sphinx 4.2.0.