映射类型¶

新式的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>)