【问题标题】:Commit changes for only one SQLAlchemy model instance when multiple have changed当多个已更改时,仅提交一个 SQLAlchemy 模型实例的更改
【发布时间】:2016-05-12 15:17:48
【问题描述】:

我查询并更改了几个实例。我只想将更改提交给其中一个。但是,当我调用db.session.commit() 时,所有更改都已提交。有没有办法单独保存一个对象,object.save(),比如 Rails 或 Django?

rule_1 = Rule.query.filter(Rule.something.like(that_thing))
rule_1.change_message = "Duplicate"

rule_2 = Rule.query.filter(Rule.something.like(that_thing))
rule_2.change_message = "This is 2nd Duplicate Message"

rule_3 = Rule.query.filter(Rule.something.like(that_thing))
rule_3.change_message = "This is the THIRD  Duplicate Message"

# What I want
rule_3.save() 

【问题讨论】:

    标签: python flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    SQLAlchemy 使用工作单元模式,而 Django、Rails 和许多其他 ORM 使用活动记录模式。这意味着属于一个会话的所有内容都作为一个单元。

    您的问题揭示的不是 SQLAlchemy 的问题,而是您的工作流程的问题。如果您不想更改这些值,则不应更改它们。如果您错误地更改了某些内容,请将其从会话中删除,而不是将其留在原处。

    rule1.change_message = 'changed rule 1'
    db.session.expunge(rule1)
    # no longer part of the session, will not be committed
    # use db.session.add(rule1) to track it again
    

    如果您确实确实需要单独的工作单元(您很可能不需要),请创建单独的会话并使用它们来查询单独的实例。

    Flask-SQLAlchemy 每个上下文使用一个会话,因此您的所有查询都将实例放在同一个会话中。 query 参数使用此默认会话。您可以通过调用create_session 创建单独的会话。确保手动清理这些会话。

    session1 = db.create_session({})
    rule1 = session1.query(Rule).filter_by(name='rule1').one()
    rule1.message = 'message'
    
    session2 = db.create_session({})
    rule2 = session2.query(Rule).filter_by(name='rule2').one()
    rule2.message = 'message'
    session2.commit()  # only commits rule2
    
    session1.close()
    session2.close()
    

    【讨论】:

      【解决方案2】:

      Rule.query 只是db.session.query(Rule) 的别名,您在同一会话中执行不同的请求,会话将作为一个整体提交。我不是专家,但要做你想做的事,你必须为每个需要的更新创建一个会话。

      这可行,但我不确定这是否是最好的方法:

      db = SQLAlchemy(app)
      # new session created from your db instance with default parameters
      new_session = db.create_session({})
      
      rule_1 = Rule.query.filter(Rule.something.like(that_thing))
      # or 
      # rule_1 = db.session.query(Rule).filter(Rule.something.like(that_thing))
      rule_1.change_message = "Duplicate"
      
      rule_2 = new_session.query(Rule).filter(Rule.something.like(that_thing))
      rule_2.change_message = "This is 2nd Duplicate Message"
      
      # update rule_1
      db.session.commit()
      
      # update rule_2
      new_session.commit()
      

      【讨论】:

        猜你喜欢
        • 2010-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-14
        • 2011-08-17
        • 2014-04-13
        相关资源
        最近更新 更多