2016-05-12 9 views
3

Ich habe mehrere Instanzen abgefragt und geändert. Ich möchte nur die Änderungen an einem von ihnen vornehmen. Alle Änderungen werden jedoch festgeschrieben, wenn ich db.session.commit() aufrufen. Gibt es eine Möglichkeit, ein Objekt einzeln zu speichern, object.save(), wie Rails oder Django?Änderungen für nur eine SQLAlchemy-Modellinstanz festschreiben, wenn sich mehrere geändert haben

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() 

Antwort

7

SQLAlchemy verwendet die Einheit der Arbeit Muster, während Django, Rails und viele andere ORMs die Active Record verwenden. Was das bedeutet ist, dass alles, was zu einer Sitzung gehört, als eine Einheit agiert.

Was Ihr Problem offenbart, ist kein Problem mit SQLAlchemy, sondern ein Problem mit Ihrem Workflow. Wenn Sie diese Werte nicht ändern möchten, sollten Sie sie nicht geändert haben. Wenn Sie etwas versehentlich ändern, löschen Sie es aus der Sitzung, anstatt es herumzulassen.

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 

Wenn Sie wirklich, wirklich, auf jeden Fall müssen separate Einheiten der Arbeit (Sie wahrscheinlich nicht), erstellen Sie separate Sitzungen und nutzen sie die einzelnen Instanzen abzufragen.

Flask-SQLAlchemy verwendet eine Sitzung pro Kontext, sodass alle Ihre Abfragen die Instanzen in derselben Sitzung platzieren. Der Parameter query verwendet diese Standardsitzung. Sie können separate Sitzungen erstellen, indem Sie create_session aufrufen. Stellen Sie sicher, diese Sitzungen manuell zu bereinigen.

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() 
0

Rule.query ist nur ein Alias ​​für db.session.query(Rule), Sie tun unterschiedlichen Antrag in derselben Sitzung wird die Sitzung als Ganzes verpflichtet werden. Ich bin kein Experte, aber um zu tun, was Sie wollen, müssen Sie für jedes Update eine Sitzung erstellen.

Dies funktioniert, aber ich bin mir nicht sicher, ob es der beste Ansatz ist:

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()