Python 将SQLAlchemy ORM和sql核心表达式中的对象连接起来?
我必须使用SQLalchemy核心表达式来获取对象,因为ORM不能进行“更新和返回”。(ORM中的更新没有返回Python 将SQLAlchemy ORM和sql核心表达式中的对象连接起来?,python,orm,sqlalchemy,object-relational-model,Python,Orm,Sqlalchemy,Object Relational Model,我必须使用SQLalchemy核心表达式来获取对象,因为ORM不能进行“更新和返回”。(ORM中的更新没有返回) 什么时候 它报告unappedInstanceError:未映射类“sqlalchemy.engine.result.RowProxy” 如何将sql表达式中的RowProxy对象放入ORM的标识映射中 ?我不确定有没有一种直接的方法来完成您所描述的,即基本上构建一个ORM对象,该对象直接映射到数据库条目,但不通过ORM执行查询 我的直觉是,这种简单的方法(只需使用数据库中的值构建i
)
什么时候
它报告unappedInstanceError:未映射类“sqlalchemy.engine.result.RowProxy”
如何将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()
我不确定你是否有一些限制,阻止你使用这种模式。该文档通过类似的简单案例工作:
可能的快速解决方案:从RowProxy
的kwargs
构造对象,因为它们类似于对象
鉴于:
rowproxy = update(User) \
.values({'name': 'Wayne'}) \
.where(User.id == subquery.as_scalar()) \
.returning() \
.fetchone()
我们或许能够做到:
user = User(**dict(rowproxy.items()))
rowproxy.items()
返回键值对的元组
dict(…)
将元组
转换为实际的键值
对;和User(…)
为model
属性名称获取kwargs
更困难的情况:
但是如果您有一个模型
,其中一个属性名
与SQL表
列名
不完全相同,该怎么办?例如,类似于:
class User(ORMBase):
# etc...
user_id = Column(name='id', etc)
{
"user_id": "id"
}
当我们试图将rowproxy
解包到User
类中时,可能会出现如下错误:TypeError:“id”是User
的无效关键字参数(因为它需要User\u id
)
现在它变脏了:我们应该有一个映射器
,了解如何从表
属性到模型
属性,反之亦然:
kw_map = {a.key: a.class_attribute.name for a in User.__mapper__.attrs}
这里,a.key
是model属性(和kwarg
),而a.class\u属性。name
是表属性。这给了我们一些类似的东西:
class User(ORMBase):
# etc...
user_id = Column(name='id', etc)
{
"user_id": "id"
}
好的,我们想实际提供从行代理
返回的值,它除了允许类似对象的访问外,还允许类似dict的访问:
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
的原因
像SQLAlchemy
这样的updatereturning
(通常)返回被更新的整个表,但没有简单的方法映射回对象,这似乎是SQLAlchemy的疏忽。不幸的是,没有比这更令人满意的答案。您可能可以从中获得一些好处:obj=User(**dict(object.items())
,但它似乎并不适用于所有情况。