新式的SQLAlchemy具有两种不同的映射器配置风格。“经典”样式是SQLAlchemy的原始映射API,而“声明性”是在“经典”之上构建的更丰富、更简洁的系统。两种样式都可以互换使用,因为每个样式的最终结果完全相同-由 mapper()
作用于可选择单元上,通常为 Table
.
这个 声明性映射 是用现代SQL方法构造映射的典型方法。利用 声明的 系统、用户定义类的组件以及 Table
将立即定义类映射到的元数据::
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
nickname = Column(String)
上面是一个包含四列的基本单表映射。其他属性(如与其他映射类的关系)也在类定义内以内联方式声明::
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
nickname = Column(String)
addresses = relationship("Address", backref="user", order_by="Address.id")
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
user_id = Column(ForeignKey('user.id'))
email_address = Column(String)
A 经典映射 引用使用 mapper()
函数,而不使用声明性系统。这是SQLAlchemy的原始类映射API,仍然是ORM提供的基本映射系统。
在“经典”形式中,表元数据是用 Table
构造,然后与 User
类通过 mapper()
功能:
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
metadata = MetaData()
user = Table('user', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(50)),
Column('nickname', String(12))
)
class User(object):
def __init__(self, name, fullname, nickname):
self.name = name
self.fullname = fullname
self.nickname = nickname
mapper(User, user)
有关映射属性(如与其他类的关系)的信息通过 properties
字典。下面的示例说明了第二个 Table
对象,映射到名为 Address
,然后链接到 User
通过 relationship()
::
address = Table('address', metadata,
Column('id', Integer, primary_key=True),
Column('user_id', Integer, ForeignKey('user.id')),
Column('email_address', String(50))
)
mapper(User, user, properties={
'addresses' : relationship(Address, backref='user', order_by=address.c.id)
})
mapper(Address, address)
在使用经典映射时,必须直接提供类,而不必使用声明性提供的“字符串查找”系统。SQL表达式通常是根据 Table
对象,即 address.c.id
以上为 Address
关系,而不是 Address.id
作为 Address
可能尚未链接到表元数据,也不能在此处指定字符串。
文档中的一些示例仍然使用经典方法,但请注意,经典方法和声明性方法 完全可互换 . 两个系统最终创建相同的配置,由 Table
,用户定义的类,与 mapper()
. 当我们谈到 mapper()
“,这也包括在使用声明性系统时-它仍然在使用,只是在幕后。
这个 Mapper
对象可从任何映射类中使用,无论方法如何, 运行时检查API 系统。使用 inspect()
功能,一个人可以获得 Mapper
从映射类:
>>> from sqlalchemy import inspect
>>> insp = inspect(User)
详细信息包括 Mapper.columns
::
>>> insp.columns
<sqlalchemy.util._collections.OrderedProperties object at 0x102f407f8>
这是一个可以以列表格式或通过单个名称查看的命名空间::
>>> list(insp.columns)
[Column('id', Integer(), table=<user>, primary_key=True, nullable=False), Column('name', String(length=50), table=<user>), Column('fullname', String(length=50), table=<user>), Column('nickname', String(length=50), table=<user>)]
>>> insp.columns.name
Column('name', String(length=50), table=<user>)
其他命名空间包括 Mapper.all_orm_descriptors
,其中包括所有映射属性以及混合、关联代理:
>>> insp.all_orm_descriptors
<sqlalchemy.util._collections.ImmutableProperties object at 0x1040e2c68>
>>> insp.all_orm_descriptors.keys()
['fullname', 'nickname', 'name', 'id']
以及 Mapper.column_attrs
::
>>> list(insp.column_attrs)
[<ColumnProperty at 0x10403fde0; id>, <ColumnProperty at 0x10403fce8; name>, <ColumnProperty at 0x1040e9050; fullname>, <ColumnProperty at 0x1040e9148; nickname>]
>>> insp.column_attrs.name
<ColumnProperty at 0x10403fce8; name>
>>> insp.column_attrs.name.expression
Column('name', String(length=50), table=<user>)