将 SQLAlchemy ORM 与 SQL Core 表达式中的对象连接起来?



我必须使用SQLalchemy Core表达式来获取对象,因为ORM无法进行"更新和返回"。(ORM中的更新没有returning)

from sqlalchemy import update
class User(ORMBase): 
...
# pure sql expression, the object returned is not ORM object.
# the object is a RowProxy.
object = update(User)  
.values({'name': 'Wayne'})  
.where(User.id == subquery.as_scalar()) 
.returning() 
.fetchone()

什么时候

db_session.add(object)

它报告UnmappedInstanceError: Class 'sqlalchemy.engine.result.RowProxy' is not mapped.

如何将 sql 表达式中的RowProxy对象放入 ORM 的身份映射中 ?

我不确定是否有一种直接的方法可以完成您所描述的操作,这本质上是构建一个直接映射到数据库条目但不通过 ORM 执行查询的 ORM 对象。

我的直觉是,天真的方法(只需使用数据库中的值构建 init ORM 对象)只会创建具有相同值的另一行(或者由于唯一性约束而失败)。

执行所要求操作的更标准方法是首先通过ORM查询行,然后从该ORM对象更新数据库。

user = User.query.filter(User.user_attribute == 'foo').one()
user.some_value = 'bar'
session.add(user)
session.commit()

我不确定你是否有一些限制,阻止你使用该模式。该文档通过类似的示例工作

简单案例:

可能的快速解决方案:从kwargsRowProxy构造对象,因为它们是类似对象的。

鉴于:

rowproxy = update(User)  
.values({'name': 'Wayne'})  
.where(User.id == subquery.as_scalar()) 
.returning() 
.fetchone()

我们也许能够做到:

user = User(**dict(rowproxy.items()))

rowproxy.items()返回key-value对的tuples;dict(...)tuples转换为实际的key-value对;User(...)model属性名称需要kwargs

更困难的情况:

但是,如果你有一个model,其中一个attribute names与SQLtablecolumn name不完全相同怎么办? 例如:

class User(ORMBase):
# etc...
user_id = Column(name='id', etc)

当我们尝试将rowproxy解压缩到User类中时,我们可能会收到如下错误:TypeError: 'id' is an invalid keyword argument for User(因为它期望的是user_id)。

现在它变得很脏:我们应该有一个关于如何从table属性到model属性的mapper,反之亦然:

kw_map = {a.key: a.class_attribute.name for a in User.__mapper__.attrs}

在这里,a.keymodel attribute(和kwarg),a.class_attribute.nametable attribute。这给了我们类似的东西:

{
"user_id": "id"
}

好吧,我们希望实际提供我们从rowproxy中获取的值,除了允许类似对象的访问外,还允许类似字典的访问:

kwargs = {a.key: rowproxy[a.class_attribute.name] for a in User.__mapper__.attrs}

现在我们可以做到:

user = User(**kwargs)

勘误表:

  • 您可能希望在调用update().returning()后立即session.commit(),以防止更改与永久存储在数据库中时相比出现长时间延迟。无需稍后session.add(user)- 您已经updated(),只需要commit()该交易
  • object是Python中的一个关键字,所以尽量不要踩它;这样做可能会得到一些非常奇怪的行为;这就是为什么我重命名为rowproxy

最新更新