SQLAlchemy:声明式更新的更好方法?

50 投票
3 回答
51398 浏览
提问于 2025-04-15 21:33

假设我有一个用户表,使用的是声明式模式:

class User(Base):
    __tablename__ = 'user'
    id = Column(u'id', Integer(), primary_key=True)
    name = Column(u'name', String(50))

当我知道用户的ID,但没有把这个用户的对象加载到会话中时,我会这样更新这个用户:

ex = update(User.__table__).where(User.id==123).values(name=u"Bob Marley")
Session.execute(ex)

我不太喜欢使用 User.__table__,我应该停止担心这个吗?

有没有更好的方法来做到这一点?

3 个回答

4

在表对象上,可以通过 update() 方法实现类似的功能。

class User(Base):
    __tablename__   = 'user'
    id = Column('id', Integer(), primary_key=True)
    name = Column('name', String(50))

stmt = User.__table__.update().where(User.id==5).values(name='user #5')

在 SQLAlchemy 中,使用 User.__table__ 就可以做到这一点。

20

你现在是在处理子句层面,而不是模型、实体或对象层面。子句层面比映射对象要低一些。没错,确实需要做一些工作来把一个术语转换成另一个术语。

你也可以停留在对象层面,做如下操作:

session = Session()
u = session.query(User).get(123)
u.name = u"Bob Marley"
session.commit()

但这样会明显变慢,因为这会导致映射对象的构建。而且我不确定这样是否更容易理解。

在你提供的例子中,我认为这是最自然和“正确”的解决方案。我不会太担心小的__table__魔法。

65

在ORM层面上也有一些更新的功能。虽然它还不能处理一些复杂的情况,但对于简单的单行更新(或者批量更新)来说,它运行得很好。它甚至会检查已经加载的对象,并对它们进行更新。你可以这样使用它:

session.query(User).filter_by(id=123).update({"name": u"Bob Marley"})

撰写回答