现代SQLAlchemy具有两种不同的映射器配置样式。“古典”风格是SQLAlchemy的原始映射API,而“声明式”则是建立在“古典”之上的更丰富,更简洁的系统。Both styles may be used interchangeably, as the end result of each is exactly the same - a user-defined class mapped by the mapper()
function onto a selectable unit, typically a Table
.
声明性映射是在现代SQLAlchemy中构建映射的典型方式。利用Declarative系统,可以立即定义用户定义类的组件以及该类映射到的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)
password = Column(String)
以上是四列的基本单表映射。其他属性,例如与其他映射类的关系,也在类定义中内联声明:
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
password = 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)
声明性映射系统在Object Relational Tutorial中引入。有关此系统如何工作的更多详细信息,请参见Declarative。
A 经典映射指的是使用mapper()
函数对映射类进行配置,而不使用Declarative系统。这是SQLAlchemy的原始类映射API,它仍然是ORM提供的基本映射系统。
在“古典”形式中,表格元数据是通过Table
结构单独创建的,然后通过mapper()
函数与User
:
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('password', String(12))
)
class User(object):
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.password = password
mapper(User, user)
有关映射属性的信息(例如与其他类的关系)通过properties
字典提供。The example below illustrates a second Table
object, mapped to a class called Address
, then linked to User
via 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)
在使用经典映射时,必须直接提供类,而没有Declarative提供的“字符串查找”系统的好处。SQL表达式通常以Table
对象的形式指定,即Address
关系的address.c.id
,而不是Address.id
,因为Address
可能尚未链接到表元数据,我们也不能在此处指定字符串。
文档中的一些示例仍然使用经典方法,但请注意经典和声明式方法完全可互换。两个系统最终都会创建相同的配置,由Table
,用户定义的类组成,它们与mapper()
链接在一起。当我们谈论“mapper()
的行为”时,这也包括在使用Declarative系统时 - 它仍然在幕后使用。
使用Runtime Inspection API系统,无论使用何种方法,Mapper
对象都可以从任何映射类中获得。使用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('password', String(length=12), 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', 'password', 'name', 'id']
>>> list(insp.column_attrs)
[<ColumnProperty at 0x10403fde0; id>, <ColumnProperty at 0x10403fce8; name>, <ColumnProperty at 0x1040e9050; fullname>, <ColumnProperty at 0x1040e9148; password>]
>>> insp.column_attrs.name
<ColumnProperty at 0x10403fce8; name>
>>> insp.column_attrs.name.expression
Column('name', String(length=50), table=<user>)