版本:1.1.0b2 |发布日期:2016年7月1日

SQLAlchemy 1.1文档

映射表列

mapper()的默认行为是将映射的Table中的所有列汇编为映射对象属性,每个列都根据列本身的名称进行命名特别是Columnkey属性)。这种行为可以通过几种方式进行修改。

命名与属性名称明显不同的列

默认情况下,映射与Column共享与映射属性相同的名称 - 具体而言,它匹配Column上的Column.key属性,默认情况下它与Column.name相同。

分配给映射到Column的Python属性的名称可以与Column.nameColumn.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_property()函数映射Column时可以指定选项。该函数明确地创建mapper()用于跟踪ColumnColumnProperty;通常,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,即firstnamelastname列:

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查询。

不存在于映射器可选择的列将不会被映射器持久化并且是有效的“只读”属性。

参数:
  • * cols - 要映射的列对象的列表。
  • active_history = False -

    True时,表示标量属性的“上一个”值在替换时应加载,如果尚未加载。通常,简单的非主键标量值的历史跟踪逻辑只需要知道“新”值就可以执行刷新。此标志可用于使用attributes.get_history()Session.is_modified()的应用程序,该应用程序还需要知道属性的“上一个”值。

    New in version 0.6.6.

  • comparator_factory – a class which extends ColumnProperty.Comparator which provides custom SQL clause generation for comparison operations.
  • group – a group name for this property when marked as deferred.
  • deferred – when True, the column property is “deferred”, meaning that it does not load immediately, and is instead loaded when the attribute is first accessed on an instance. 另见deferred()
  • doc – optional string that will be applied as the doc on the class-bound descriptor.
  • expire_on_flush = True -

    在刷新时禁用过期。引用SQL表达式(而不是单个表绑定列)的column_property()被认为是“只读”属性;填充它对数据状态没有影响,它只能返回数据库状态。出于这个原因,只要父对象涉及到刷新,即在刷新中有任何种类的“脏”状态,column_property()的值就会过期。将该参数设置为False将产生在刷新过程结束后保留​​现有值的效果。但请注意,具有默认到期设置的Session仍会在Session.commit()调用之后过期所有属性。

    New in version 0.7.3.

  • info -

    可选数据字典,将填充到此对象的MapperProperty.info属性中。

    0.8版本中的新功能

  • extension – an AttributeExtension instance, or list of extensions, which will be prepended to the list of attribute listeners for the resulting descriptor placed on the class. 已过时。 T0>请参阅AttributeEvents

映射表列的子集

有时,使用Reflecting Database Objects中描述的反映过程来使Table对象可用于从数据库加载表结构。对于有很多不需要在应用程序中引用的列的表,可以使用include_propertiesexclude_properties参数指定只有列的子集应该是映射。例如:

class User(Base):
    __table__ = user_table
    __mapper_args__ = {
        'include_properties' :['user_id', 'user_name']
    }

...将User类映射到user_table表,仅包括user_iduser_name列 - 其余未被引用。同理:

class Address(Base):
    __table__ = address_table
    __mapper_args__ = {
        'exclude_properties' : ['street', 'city', 'state', 'zip']
    }

...将Address类映射到address_table表,其中包括除streetcity之外的所有列。 statezip

使用此映射时,未包含的列将不会在由Query发出的任何SELECT语句中引用,也不会在表示该列的映射类上存在任何映射属性;分配该名称的属性将不会超出正常Python属性分配的作用。

在某些情况下,多个列可能具有相同的名称,例如映射到共享某个列名的两个或多个表的连接时。include_propertiesexclude_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. 这是因为在defaultupdate的情况下,Column对象仍然存在于Table中,从而允许默认函数在ORM发出INSERT或UPDATE时发生,而在server_defaultserver_onupdate的情况下,关系数据库本身维护这些函数。