SqlAlchemy 2.0 中文文档(七十七)(3)https://developer.aliyun.com/article/1561179
新特性
事件移除 API
使用 listen()
或 listens_for()
建立的事件现在可以使用新的 remove()
函数进行移除。传递给 remove()
的 target
、identifier
和 fn
参数需要与用于监听的参数完全匹配,事件将从所有已建立的位置移除:
@event.listens_for(MyClass, "before_insert", propagate=True) def my_before_insert(mapper, connection, target): """listen for before_insert""" # ... event.remove(MyClass, "before_insert", my_before_insert)
在上述示例中,设置了 propagate=True
标志。这意味着 my_before_insert()
被建立为 MyClass
及其所有子类的监听器。系统跟踪了 my_before_insert()
监听器函数作为此调用的结果放置的所有位置,并作为调用 remove()
的结果将其移除。
移除系统使用注册表将传递给 listen()
的参数与事件监听器的集合相关联,这些事件监听器在许多情况下是原始用户提供的函数的包装版本。该注册表大量使用弱引用,以允许所有包含的内容(例如监听器目标)在超出范围时被垃圾回收。
#2268 ### 新查询选项 API;load_only()
选项
加载器选项系统,如joinedload()
、subqueryload()
、lazyload()
、defer()
等,都建立在一个名为Load
的新系统之上。Load
提供了一种“方法链式”(又名生成式)的加载器选项方法,因此,不再需要使用点号或多个属性名称将长路径连接在一起,而是为每个路径明确指定加载器样式。
虽然新方法稍微更冗长,但更容易理解,因为对哪些路径应用了哪些选项没有歧义;它简化了选项的方法签名,并为基于列的选项提供了更大的灵活性。旧系统将继续无限期保持功能,并且所有样式都可以混合使用。
旧方法
要在多元素路径中的每个链接上设置某种加载样式,必须使用_all()
选项:
query(User).options(joinedload_all("orders.items.keywords"))
新方法
现在加载器选项是可链接的,因此相同的joinedload(x)
方法等同地应用于每个链接,无需在joinedload()
和joinedload_all()
之间保持清晰:
query(User).options(joinedload("orders").joinedload("items").joinedload("keywords"))
旧方法
在基于子类的路径上设置一个选项需要将路径中的所有链接拼写为类绑定属性,因为PropComparator.of_type()
方法需要被调用:
session.query(Company).options( subqueryload_all(Company.employees.of_type(Engineer), Engineer.machines) )
新方法
只有那些实际需要PropComparator.of_type()
的路径中的元素需要被设置为类绑定属性,之后可以恢复基于字符串的名称:
session.query(Company).options( subqueryload(Company.employees.of_type(Engineer)).subqueryload("machines") )
旧方法
在长路径中的最后一个链接上设置加载器选项使用的语法看起来很像应该为路径中的所有链接设置选项,导致混淆:
query(User).options(subqueryload("orders.items.keywords"))
新方法
现在可以使用defaultload()
为路径中的条目拼写出路径,其中现有的加载器样式不应更改。更冗长但意图更清晰:
query(User).options(defaultload("orders").defaultload("items").subqueryload("keywords"))
仍然可以利用点号样式,特别是在跳过几个路径元素的情况下:
query(User).options(defaultload("orders.items").subqueryload("keywords"))
旧方法
在路径上使用defer()
选项需要为每个列明确指定完整路径:
query(User).options(defer("orders.description"), defer("orders.isopen"))
新方式
到达目标路径的单个Load
对象可以反复调用Load.defer()
:
query(User).options(defaultload("orders").defer("description").defer("isopen"))
Load 类
Load
类可以直接用于提供“绑定”目标,特别是当存在多个父实体时:
from sqlalchemy.orm import Load query(User, Address).options(Load(Address).joinedload("entries"))
仅加载
一个新选项load_only()
实现了“除了延迟加载一切之外”的加载方式,仅加载给定的列,并延迟其余部分:
from sqlalchemy.orm import load_only query(User).options(load_only("name", "fullname")) # specify explicit parent entity query(User, Address).options(Load(User).load_only("name", "fullname")) # specify path query(User).options(joinedload(User.addresses).load_only("email_address"))
类特定的通配符
使用Load
,可以使用通配符为给定实体上的所有关系(或者列)设置加载方式,而不影响其他实体:
# lazyload all User relationships query(User).options(Load(User).lazyload("*")) # undefer all User columns query(User).options(Load(User).undefer("*")) # lazyload all Address relationships query(User).options(defaultload(User.addresses).lazyload("*")) # undefer all Address columns query(User).options(defaultload(User.addresses).undefer("*"))
#1418 ### 新的text()
功能
text()
构造获得了新的方法:
TextClause.bindparams()
允许灵活设置绑定参数类型和值:
# setup values stmt = text( "SELECT id, name FROM user WHERE name=:name AND timestamp=:timestamp" ).bindparams(name="ed", timestamp=datetime(2012, 11, 10, 15, 12, 35)) # setup types and/or values stmt = ( text("SELECT id, name FROM user WHERE name=:name AND timestamp=:timestamp") .bindparams(bindparam("name", value="ed"), bindparam("timestamp", type_=DateTime())) .bindparam(timestamp=datetime(2012, 11, 10, 15, 12, 35)) )
TextClause.columns()
取代了text()
的typemap
选项,返回一个新的构造TextAsFrom
:
# turn a text() into an alias(), with a .c. collection: stmt = text("SELECT id, name FROM user").columns(id=Integer, name=String) stmt = stmt.alias() stmt = select([addresses]).select_from( addresses.join(stmt), addresses.c.user_id == stmt.c.id ) # or into a cte(): stmt = text("SELECT id, name FROM user").columns(id=Integer, name=String) stmt = stmt.cte("x") stmt = select([addresses]).select_from( addresses.join(stmt), addresses.c.user_id == stmt.c.id )
#2877 ### 从 SELECT 中插入
经过几乎多年的毫无意义的拖延,这个相对较小的语法特性已经被添加,并且也被回溯到 0.8.3,所以在技术上在 0.9 中并不是“新”的。一个select()
构造或其他兼容的构造可以传递给新方法Insert.from_select()
,在那里它将被用于渲染一个INSERT .. SELECT
构造:
>>> from sqlalchemy.sql import table, column >>> t1 = table("t1", column("a"), column("b")) >>> t2 = table("t2", column("x"), column("y")) >>> print(t1.insert().from_select(["a", "b"], t2.select().where(t2.c.y == 5))) INSERT INTO t1 (a, b) SELECT t2.x, t2.y FROM t2 WHERE t2.y = :y_1
这个结构足够智能,也可以适应 ORM 对象,比如类和Query
对象:
s = Session() q = s.query(User.id, User.name).filter_by(name="ed") ins = insert(Address).from_select((Address.id, Address.email_address), q)
渲染:
INSERT INTO addresses (id, email_address) SELECT users.id AS users_id, users.name AS users_name FROM users WHERE users.name = :name_1
#722 ### select()
、Query()
上的新 FOR UPDATE 支持
尝试简化在 Core 和 ORM 中对 SELECT
语句中的 FOR UPDATE
子句的规范,并支持 PostgreSQL 和 Oracle 支持的 FOR UPDATE OF
SQL。
使用核心GenerativeSelect.with_for_update()
,可以单独指定FOR SHARE
和NOWAIT
等选项,而不是链接到任意字符串代码:
stmt = select([table]).with_for_update(read=True, nowait=True, of=table)
在 Posgtresql 上,上述语句可能会呈现如下:
SELECT table.a, table.b FROM table FOR SHARE OF table NOWAIT
Query
对象获得了类似的方法 Query.with_for_update()
,其行为方式相同。该方法取代了现有的 Query.with_lockmode()
方法,该方法使用不同的系统翻译 FOR UPDATE
子句。目前,“lockmode”字符串参数仍然被 Session.refresh()
方法接受。 ### 本机浮点字符串转换精度可配置的浮点类型
每当 DBAPI 返回要转换为 Python Decimal()
的 Python 浮点类型时,SQLAlchemy 所做的转换必然涉及将浮点值转换为字符串的中间步骤。此字符串转换的比例以前是硬编码为 10,现在可配置。该设置可用于 Numeric
以及 Float
类型,以及所有 SQL 和方言特定的后代类型,使用参数 decimal_return_scale
。如果类型支持 .scale
参数,例如 Numeric
和一些浮点类型如 DOUBLE
,则如果未另行指定,.scale
的值将用作 .decimal_return_scale
的默认值。如果 .scale
和 .decimal_return_scale
都不存在,则默认值为 10。例如:
from sqlalchemy.dialects.mysql import DOUBLE import decimal data = Table( "data", metadata, Column("double_value", mysql.DOUBLE(decimal_return_scale=12, asdecimal=True)), ) conn.execute( data.insert(), double_value=45.768392065789, ) result = conn.scalar(select([data.c.double_value])) # previously, this would typically be Decimal("45.7683920658"), # e.g. trimmed to 10 decimal places # now we get 12, as requested, as MySQL can support this # much precision for DOUBLE assert result == decimal.Decimal("45.768392065789")
#2867 ### ORM 查询的列捆绑
Bundle
允许查询一组列,然后将它们分组为查询返回的元组下的一个名称。Bundle
的最初目的是 1. 允许将“复合”ORM 列作为列式结果集中的单个值返回,而不是将它们扩展为单独的列,以及 2. 允许在 ORM 中创建自定义结果集构造,使用临时列和返回类型,而不涉及映射类的更重量级机制。
另请参阅
当按属性基础查询时,复合属性现在以其对象形式返回
使用 Bundles 分组选定属性
服务器端版本计数
ORM 的版本控制功能(现在也在配置版本计数器中记录)现在可以利用服务器端版本计数方案,例如由触发器或数据库系统列生成的方案,以及版本 _id_counter 函数本身之外的条件编程方案。通过向 version_id_generator
参数提供值 False
,ORM 将使用已设置的版本标识符,或者在发出 INSERT 或 UPDATE 时同时从每行获取版本标识符。当使用服务器生成的版本标识符时,强烈建议仅在具有强大 RETURNING 支持的后端上使用此功能(PostgreSQL、SQL Server;Oracle 也支持 RETURNING,但 cx_oracle 驱动程序仅支持有限),否则额外的 SELECT 语句将增加显著的性能开销。服务器端版本计数器提供的示例说明了如何使用 PostgreSQL 的 xmin
系统列将其与 ORM 的版本控制功能集成。
另请参阅
服务器端版本计数器
include_backrefs=False
选项用于 @validates
validates()
函数现在接受一个选项 include_backrefs=True
,这将跳过为从反向引用发起的事件触发验证器的情况:
from sqlalchemy import Column, Integer, ForeignKey from sqlalchemy.orm import relationship, validates from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class A(Base): __tablename__ = "a" id = Column(Integer, primary_key=True) bs = relationship("B", backref="a") @validates("bs") def validate_bs(self, key, item): print("A.bs validator") return item class B(Base): __tablename__ = "b" id = Column(Integer, primary_key=True) a_id = Column(Integer, ForeignKey("a.id")) @validates("a", include_backrefs=False) def validate_a(self, key, item): print("B.a validator") return item a1 = A() a1.bs.append(B()) # prints only "A.bs validator"
PostgreSQL JSON 类型
PostgreSQL 方言现在具有一个 JSON
类型,以补充 HSTORE
类型。
另请参阅
JSON
自动映射扩展
新的扩展在0.9.1中添加,称为sqlalchemy.ext.automap
。这是一个实验性扩展,它扩展了声明式的功能以及DeferredReflection
类的功能。基本上,该扩展提供了一个基类AutomapBase
,根据给定的表元数据自动生成映射类和它们之间的关系。
正常使用的MetaData
可能是通过反射生成的,但不要求使用反射。最基本的用法说明了sqlalchemy.ext.automap
如何根据反射模式提供映射类,包括关系:
from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import Session from sqlalchemy import create_engine Base = automap_base() # engine, suppose it has two tables 'user' and 'address' set up engine = create_engine("sqlite:///mydatabase.db") # reflect the tables Base.prepare(engine, reflect=True) # mapped classes are now created with names matching that of the table # name. User = Base.classes.user Address = Base.classes.address session = Session(engine) # rudimentary relationships are produced session.add(Address(email_address="foo@bar.com", user=User(name="foo"))) session.commit() # collection-based relationships are by default named "<classname>_collection" print(u1.address_collection)
此外,AutomapBase
类是一个声明性基类,并支持所有声明性的功能。可以使用“自动映射”功能与现有的明确定义的模式一起使用,仅生成关系和缺失类。命名方案和关系生成例程可以使用可调用函数来插入。
期望AutomapBase
系统提供了一个快速且现代化的解决方案,解决了非常著名的SQLSoup也尝试解决的问题,即从现有数据库动态生成快速和简陋的对象模型的问题。通过严格在映射器配置级别解决该问题,并与现有的声明式类技术完全集成,AutomapBase
旨在为快速自动生成临时映射的问题提供一个良好集成的方法。
另请参阅
自动映射 ### 事件移除 API
使用listen()
或listens_for()
建立的事件现在可以使用新的remove()
函数进行移除。发送给remove()
的target
、identifier
和fn
参数需要与用于监听的参数完全匹配,并且事件将从建立的所有位置中移除:
@event.listens_for(MyClass, "before_insert", propagate=True) def my_before_insert(mapper, connection, target): """listen for before_insert""" # ... event.remove(MyClass, "before_insert", my_before_insert)
在上面的示例中,设置了propagate=True
标志。这意味着my_before_insert()
被建立为MyClass
以及MyClass
的所有子类的监听器。系统跟踪了my_before_insert()
监听函数作为此调用的结果放置的所有位置,并在调用remove()
后将其移除。
移除系统使用注册表将传递给listen()
的参数与事件监听器集合关联,这些事件监听器在许多情况下是原始用户提供的函数的包装版本。该注册表大量使用弱引用,以允许所有包含的内容(如监听器目标)在超出范围时被垃圾回收。
新查询选项 API;load_only()
选项
加载器选项系统,如joinedload()
、subqueryload()
、lazyload()
、defer()
等,都建立在一个名为Load
的新系统之上。Load
提供了一种“方法链式”(又名生成式)的加载器选项方法,因此不再需要使用点号或多个属性名称连接长路径,而是为每个路径指定明确的加载器样式。
新方法虽然稍微冗长,但更容易理解,因为对应哪些路径应用了哪些选项没有歧义;它简化了选项的方法签名,并为基于列的选项提供了更大的灵活性。旧系统将永远保持功能,并且所有样式都可以混合使用。
旧方法
要在多元素路径中的每个链接上设置特定的加载样式,必须使用_all()
选项:
query(User).options(joinedload_all("orders.items.keywords"))
新方法
加载器选项现在可以链式调用,因此相同的joinedload(x)
方法同样适用于每个链接,无需在joinedload()
和joinedload_all()
之间保持清晰:
query(User).options(joinedload("orders").joinedload("items").joinedload("keywords"))
旧方法
在基于子类的路径上设置选项需要将路径中的所有链接拼写为类绑定属性,因为需要调用PropComparator.of_type()
方法:
session.query(Company).options( subqueryload_all(Company.employees.of_type(Engineer), Engineer.machines) )
新方法
只有实际需要PropComparator.of_type()
的路径元素需要��置为类绑定属性,之后可以恢复基于字符串的名称:
session.query(Company).options( subqueryload(Company.employees.of_type(Engineer)).subqueryload("machines") )
旧方法
在长路径中设置加载器选项的最后一个链接使用的语法看起来很像应该为路径中的所有链接设置选项,导致混淆:
query(User).options(subqueryload("orders.items.keywords"))
新方法
现在可以使用defaultload()
来拼写路径,其中现有的加载器样式应保持不变。更冗长但意图更清晰:
query(User).options(defaultload("orders").defaultload("items").subqueryload("keywords"))
点线样式仍然可以被充分利用,特别是在跳过多个路径元素的情况下:
query(User).options(defaultload("orders.items").subqueryload("keywords"))
旧方法
需要为路径上的每个列拼写出完整路径的defer()
选项:
query(User).options(defer("orders.description"), defer("orders.isopen"))
新方法
到达目标路径的单个Load
对象可以反复调用Load.defer()
:
query(User).options(defaultload("orders").defer("description").defer("isopen"))
加载类
Load
类可以直接用于提供“绑定”目标,特别是当存在多个父实体时:
from sqlalchemy.orm import Load query(User, Address).options(Load(Address).joinedload("entries"))
仅加载
新选项load_only()
实现了“除了加载之外的一切都延迟”的加载方式,仅加载给定列并推迟其余部分:
from sqlalchemy.orm import load_only query(User).options(load_only("name", "fullname")) # specify explicit parent entity query(User, Address).options(Load(User).load_only("name", "fullname")) # specify path query(User).options(joinedload(User.addresses).load_only("email_address"))
类特定通配符
使用Load
,可以使用通配符为给定实体上的所有关系(或可能列)设置加载,而不影响其他实体:
# lazyload all User relationships query(User).options(Load(User).lazyload("*")) # undefer all User columns query(User).options(Load(User).undefer("*")) # lazyload all Address relationships query(User).options(defaultload(User.addresses).lazyload("*")) # undefer all Address columns query(User).options(defaultload(User.addresses).undefer("*"))
加载类
Load
类可以直接用于提供“绑定”目标,特别是当存在多个父实体时:
from sqlalchemy.orm import Load query(User, Address).options(Load(Address).joinedload("entries"))
仅加载
新选项load_only()
实现了“除了加载之外的一切都延迟加载”的加载方式,仅加载给定的列并推迟其余的列:
from sqlalchemy.orm import load_only query(User).options(load_only("name", "fullname")) # specify explicit parent entity query(User, Address).options(Load(User).load_only("name", "fullname")) # specify path query(User).options(joinedload(User.addresses).load_only("email_address"))
类特定的通配符
使用Load
,可以使用通配符为给定实体上的所有关系(或可能是列)设置加载,而不影响其他实体:
# lazyload all User relationships query(User).options(Load(User).lazyload("*")) # undefer all User columns query(User).options(Load(User).undefer("*")) # lazyload all Address relationships query(User).options(defaultload(User.addresses).lazyload("*")) # undefer all Address columns query(User).options(defaultload(User.addresses).undefer("*"))
新的text()
功能
text()
构造获得了新方法:
TextClause.bindparams()
允许灵活设置绑定参数类型和值:
# setup values stmt = text( "SELECT id, name FROM user WHERE name=:name AND timestamp=:timestamp" ).bindparams(name="ed", timestamp=datetime(2012, 11, 10, 15, 12, 35)) # setup types and/or values stmt = ( text("SELECT id, name FROM user WHERE name=:name AND timestamp=:timestamp") .bindparams(bindparam("name", value="ed"), bindparam("timestamp", type_=DateTime())) .bindparam(timestamp=datetime(2012, 11, 10, 15, 12, 35)) )
TextClause.columns()
取代了text()
的typemap
选项,返回一个新的构造TextAsFrom
:
# turn a text() into an alias(), with a .c. collection: stmt = text("SELECT id, name FROM user").columns(id=Integer, name=String) stmt = stmt.alias() stmt = select([addresses]).select_from( addresses.join(stmt), addresses.c.user_id == stmt.c.id ) # or into a cte(): stmt = text("SELECT id, name FROM user").columns(id=Integer, name=String) stmt = stmt.cte("x") stmt = select([addresses]).select_from( addresses.join(stmt), addresses.c.user_id == stmt.c.id )
从 SELECT 插入
经过几乎多年的毫无意义的拖延,这个相对较小的语法特性已经被添加,并且也被回溯到了 0.8.3 版本,所以在技术上在 0.9 版本中并不是“新”功能。可以将select()
构造或其他兼容的构造传递给新方法Insert.from_select()
,其中它将被用于渲染INSERT .. SELECT
构造:
>>> from sqlalchemy.sql import table, column >>> t1 = table("t1", column("a"), column("b")) >>> t2 = table("t2", column("x"), column("y")) >>> print(t1.insert().from_select(["a", "b"], t2.select().where(t2.c.y == 5))) INSERT INTO t1 (a, b) SELECT t2.x, t2.y FROM t2 WHERE t2.y = :y_1
该构造足够智能,也可以适应 ORM 对象,如类和Query
对象:
s = Session() q = s.query(User.id, User.name).filter_by(name="ed") ins = insert(Address).from_select((Address.id, Address.email_address), q)
渲染:
INSERT INTO addresses (id, email_address) SELECT users.id AS users_id, users.name AS users_name FROM users WHERE users.name = :name_1
select()
,Query()
上的新的 FOR UPDATE 支持
尝试简化在 Core 和 ORM 中制作SELECT
语句时FOR UPDATE
子句的规范,并支持 PostgreSQL 和 Oracle 支持的FOR UPDATE OF
SQL。
使用核心GenerativeSelect.with_for_update()
,可以单独指定选项,如FOR SHARE
和NOWAIT
,而不是链接到任意字符串代码:
stmt = select([table]).with_for_update(read=True, nowait=True, of=table)
在 Posgtresql 上述语句可能会呈现如下:
SELECT table.a, table.b FROM table FOR SHARE OF table NOWAIT
Query
对象获得了一个类似的方法 Query.with_for_update()
,其行为方式相同。该方法取代了现有的 Query.with_lockmode()
方法,该方法使用不同的系统翻译 FOR UPDATE
子句。目前,“lockmode” 字符串参数仍然被 Session.refresh()
方法接受。
本机浮点字符串转换精度可配置
每当 DBAPI 返回一个要转换为 Python Decimal()
的 Python 浮点类型时,SQLAlchemy 所做的转换必然涉及一个中间步骤,将浮点值转换为字符串。用于此字符串转换的标度以前是硬编码为 10,现在是可配置的。该设置在 Numeric
以及 Float
类型上都可用,以及所有 SQL 和特定方言的后代类型,使用参数 decimal_return_scale
。如果类型支持 .scale
参数,如 Numeric
和一些浮点类型如 DOUBLE
,则如果未另行指定,则 .scale
的值将用作 .decimal_return_scale
的默认值。如果 .scale
和 .decimal_return_scale
都不存在,则默认值为 10。例如:
from sqlalchemy.dialects.mysql import DOUBLE import decimal data = Table( "data", metadata, Column("double_value", mysql.DOUBLE(decimal_return_scale=12, asdecimal=True)), ) conn.execute( data.insert(), double_value=45.768392065789, ) result = conn.scalar(select([data.c.double_value])) # previously, this would typically be Decimal("45.7683920658"), # e.g. trimmed to 10 decimal places # now we get 12, as requested, as MySQL can support this # much precision for DOUBLE assert result == decimal.Decimal("45.768392065789")
ORM 查询的列捆绑
Bundle
允许查询一组列,然后将它们分组为查询返回的元组下的一个名称。Bundle
的最初目的是 1. 允许将“复合”ORM 列作为列结果集中的单个值返回,而不是将它们展开为单独的列,以及 2. 允许在 ORM 中创建自定义结果集构造,使用临时列和返回类型,而不涉及映射类的更重量级机制。
另请参见
当按属性基础查询时,复合属性现在以其对象形式返回
使用捆绑组合选定属性
服务器端版本计数
ORM 的版本控制功能(现在还在 配置版本计数器 中有文档记录)现在可以利用服务器端的版本计数方案,例如由触发器或数据库系统列生成的方案,以及版本 _id_counter 函数本身之外的条件编程方案。通过向 version_id_generator
参数提供值 False
,ORM 将使用已设置的版本标识符,或者在发出 INSERT 或 UPDATE 时同时从每一行获取版本标识符。当使用服务器生成的版本标识符时,强烈建议仅在具有强大 RETURNING 支持的后端上使用此功能(PostgreSQL、SQL Server;Oracle 也支持 RETURNING,但 cx_oracle 驱动程序仅具有有限的支持),否则额外的 SELECT 语句将增加显著的性能开销。在 服务器端版本计数器 提供的示例中说明了使用 PostgreSQL xmin
系统列将其与 ORM 的版本控制功能集成的用法。
另请参阅
服务器端版本计数器
include_backrefs=False
选项用于 @validates
validates()
函数现在接受一个选项 include_backrefs=True
,将为从反向引用发起事件的情况跳过触发器:
from sqlalchemy import Column, Integer, ForeignKey from sqlalchemy.orm import relationship, validates from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class A(Base): __tablename__ = "a" id = Column(Integer, primary_key=True) bs = relationship("B", backref="a") @validates("bs") def validate_bs(self, key, item): print("A.bs validator") return item class B(Base): __tablename__ = "b" id = Column(Integer, primary_key=True) a_id = Column(Integer, ForeignKey("a.id")) @validates("a", include_backrefs=False) def validate_a(self, key, item): print("B.a validator") return item a1 = A() a1.bs.append(B()) # prints only "A.bs validator"
PostgreSQL JSON 类型
PostgreSQL 方言现在具有 JSON
类型,以补充 HSTORE
类型。
另请参阅
JSON
Automap 扩展
0.9.1 版本新增了一个名为sqlalchemy.ext.automap
的扩展。这是一个实验性扩展,它扩展了声明式以及DeferredReflection
类的功能。本质上,该扩展提供了一个基类AutomapBase
,根据给定的表元数据自动生成映射类和它们之间的关系。
使用的MetaData
通常可能是通过反射生成的,但不要求使用反射。最基本的用法说明了sqlalchemy.ext.automap
如何能够根据反射模式提供映射类,包括关系:
from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import Session from sqlalchemy import create_engine Base = automap_base() # engine, suppose it has two tables 'user' and 'address' set up engine = create_engine("sqlite:///mydatabase.db") # reflect the tables Base.prepare(engine, reflect=True) # mapped classes are now created with names matching that of the table # name. User = Base.classes.user Address = Base.classes.address session = Session(engine) # rudimentary relationships are produced session.add(Address(email_address="foo@bar.com", user=User(name="foo"))) session.commit() # collection-based relationships are by default named "<classname>_collection" print(u1.address_collection)
此外,AutomapBase
类是一个声明基类,并支持声明的所有功能。可以将“自动映射”功能用于现有的、明确声明的模式,以仅生成关系和缺失类。可以使用可调用函数添加命名方案和关系生成例程。
希望AutomapBase
系统提供了一个快速且现代化的解决方案,解决了非常著名的SQLSoup也试图解决的问题,即从现有数据库快速生成一个简单的对象模型。通过严格在映射器配置级别解决该问题,并与现有的声明类技术完全集成,AutomapBase
旨在提供一个完全集成的方法来解决迅速自动生成临时映射的问题。
另请参阅
自动映射
SqlAlchemy 2.0 中文文档(七十七)(5)https://developer.aliyun.com/article/1561184