【问题标题】:SQLAlchemy: a better way for update with declarative?SQLAlchemy:使用声明式更新的更好方法?
【发布时间】:2011-02-07 14:01:16
【问题描述】:

我是 SQLAlchemy 菜鸟。

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

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__,我应该停止担心吗?

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

谢谢!

【问题讨论】:

标签: python sqlalchemy declarative


【解决方案1】:

还有一些 ORM 级别的更新功能。它还没有处理任何棘手的情况,但对于单行更新(或批量更新)的琐碎情况,它可以正常工作。它甚至会遍历任何已加载的对象并对其应用更新。你可以这样使用它:

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

【讨论】:

  • 这不考虑用户为列分配的变量名称 - 如果名称被声明为 user_name = Column("name", String(50)),这将失败 b/c 实际列的名称是必需的。谁能解释这是为什么?
  • 不应该是.get(123).filter_by(id == 123) 吗?
  • @Brendan filterfilter_by 是不同的方法。前者采用表达式作为参数,而后者采用关键字参数。
  • @Kira:回复晚了,但我会添加它以防其他人需要它。 session.query(User).filter_by(id=123).update({User.name: "Bob Marley"})
  • @RichardLaw 不,FOR UPDATE 不是UPDATE 语句的一部分,SQLA 只是忽略了with_for_update()
【解决方案2】:

您在此处处理 子句 级别,而不是模型/实体/对象级别。子句级别低于映射对象。是的,必须做一些事情才能将一个术语转换为其他术语。

您也可以停留在对象级别并执行以下操作:

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

但它会明显变慢,因为它会导致映射对象构造。而且我不确定它是否更具可读性。

在您提供的示例中,我看到了最自然和“正确”的解决方案。我不会担心小__table__魔术。

【讨论】:

    【解决方案3】:

    通过 Table 对象上的 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')
    

    使用User.__table__ 是它在 SQLAlchemy 中的完成方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多