mapper()
的默认行为是将映射的Table
中的所有列汇编为映射对象属性,每个列都根据列本身的名称进行命名特别是Column
的key
属性)。这种行为可以通过几种方式进行修改。
默认情况下,映射与Column
共享与映射属性相同的名称 - 具体而言,它匹配Column
上的Column.key
属性,默认情况下它与Column.name
相同。
分配给映射到Column
的Python属性的名称可以与Column.name
或Column.key
不同,只需通过指定正如我们在声明性映射中所说明的那样:
class User(Base):
__tablename__ = 'user'
id = Column('user_id', Integer, primary_key=True)
name = Column('user_name', String(50))
Where above User.id
resolves to a column named user_id
and User.name
resolves to a column named user_name
.
映射到现有表格时,可以直接引用Column
对象:
class User(Base):
__table__ = user_table
id = user_table.c.user_id
name = user_table.c.user_name
或者在经典的映射中,使用所需的键将其放置在properties
字典中:
mapper(User, user_table, properties={
'id': user_table.c.user_id,
'name': user_table.c.user_name,
})
在下一节中,我们将更仔细地检查.key
的用法。
在上一节Naming Columns Distinctly from Attribute Names中,我们展示了显式映射到类的Column
如何可以具有与该列不同的属性名称。但是,如果我们没有明确列出Column
对象,而是使用反射自动生成Table
对象(例如,如Reflecting Database Objects在这种情况下,我们可以利用DDLEvents.column_reflect()
事件来拦截Column
对象的生成并为它们提供Column.key
@event.listens_for(Table, "column_reflect")
def column_reflect(inspector, table, column_info):
# set column.key = "attr_<lower_case_name>"
column_info['key'] = "attr_%s" % column_info['name'].lower()
通过上述事件,Column
对象的反射将被我们的事件拦截,该事件添加了一个新的“.key”元素,如下图所示:
class MyClass(Base):
__table__ = Table("some_table", Base.metadata,
autoload=True, autoload_with=some_engine)
如果我们想限定事件只对上面的特定MetaData
对象作出反应,我们可以在我们的事件中检查它:
@event.listens_for(Table, "column_reflect")
def column_reflect(inspector, table, column_info):
if table.metadata is Base.metadata:
# set column.key = "attr_<lower_case_name>"
column_info['key'] = "attr_%s" % column_info['name'].lower()
通常在映射到现有的Table
对象时使用column_prefix
作为列名前缀的快速方法:
class User(Base):
__table__ = user_table
__mapper_args__ = {'column_prefix':'_'}
以上将放置诸如_user_id
,_user_name
,_password
等属性名称。在映射的User
类上。
这种方法在现代用法中不常见。为了处理反映表,更灵活的方法是使用Automating Column Naming Schemes from Reflected Tables中描述的方法。
使用column_property()
函数映射Column
时可以指定选项。该函数明确地创建mapper()
用于跟踪Column
的ColumnProperty
;通常,mapper()
会自动创建它。使用column_property()
,我们可以传递关于如何映射Column
的额外参数。下面,我们传递一个选项active_history
,该选项指定对此列值的更改应导致先前加载的值为前者:
from sqlalchemy.orm import column_property
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = column_property(Column(String(50)), active_history=True)
column_property()
is also used to map a single attribute to multiple columns. 这个用例映射到一个join()
,它具有彼此相等的属性:
class User(Base):
__table__ = user.join(address)
# assign "user.id", "address.user_id" to the
# "id" attribute
id = column_property(user_table.c.id, address_table.c.user_id)
有关此用法的更多示例,请参阅Mapping a Class against Multiple Tables。
需要column_property()
的另一个地方是将SQL表达式指定为映射属性,比如下面我们创建的属性fullname
,即firstname
和lastname
列:
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
firstname = Column(String(50))
lastname = Column(String(50))
fullname = column_property(firstname + " " + lastname)
在SQL Expressions as Mapped Attributes中查看此用法的示例。
sqlalchemy.orm.
column_property
(*columns, **kwargs)¶提供用于Mapper的列级属性。
通常可以直接使用Column
元素将基于列的属性应用于映射器的properties
字典。当给定的列不直接存在于映射器的可选择范围内时使用此函数;示例包括SQL表达式,函数和标量SELECT查询。
不存在于映射器可选择的列将不会被映射器持久化并且是有效的“只读”属性。
参数: |
|
---|
有时,使用Reflecting Database Objects中描述的反映过程来使Table
对象可用于从数据库加载表结构。对于有很多不需要在应用程序中引用的列的表,可以使用include_properties
或exclude_properties
参数指定只有列的子集应该是映射。例如:
class User(Base):
__table__ = user_table
__mapper_args__ = {
'include_properties' :['user_id', 'user_name']
}
...将User
类映射到user_table
表,仅包括user_id
和user_name
列 - 其余未被引用。同理:
class Address(Base):
__table__ = address_table
__mapper_args__ = {
'exclude_properties' : ['street', 'city', 'state', 'zip']
}
...将Address
类映射到address_table
表,其中包括除street
,city
之外的所有列。 state
和zip
。
使用此映射时,未包含的列将不会在由Query
发出的任何SELECT语句中引用,也不会在表示该列的映射类上存在任何映射属性;分配该名称的属性将不会超出正常Python属性分配的作用。
在某些情况下,多个列可能具有相同的名称,例如映射到共享某个列名的两个或多个表的连接时。include_properties
和exclude_properties
也可以容纳Column
对象来更准确地描述应该包含或排除哪些列:
class UserAddress(Base):
__table__ = user_table.join(addresses_table)
__mapper_args__ = {
'exclude_properties' :[address_table.c.id],
'primary_key' : [user_table.c.id]
}
注意
insert and update defaults configured on individual Column
objects, i.e. those described at Column Insert/Update Defaults including those configured by the default
, update
, server_default
and server_onupdate
arguments, will continue to function normally even if those Column
objects are not mapped. 这是因为在default
和update
的情况下,Column
对象仍然存在于Table
中,从而允许默认函数在ORM发出INSERT或UPDATE时发生,而在server_default
和server_onupdate
的情况下,关系数据库本身维护这些函数。