2015-11-18 6 views
8

Ich frage mich, wie SQLAlchemy Änderungen verfolgt, die außerhalb von SQLAlchemy gemacht werden (manuelle Änderung zum Beispiel)?Wie verfolgt SQLAlchemy Datenbankänderungen?

Bis jetzt habe ich db.session.commit() vor jedem Wert gesetzt, der außerhalb von SQLAlchemy geändert werden kann. Ist das eine schlechte Übung? Wenn ja, gibt es einen besseren Weg, um sicherzustellen, dass ich den neuesten Wert habe? Ich habe tatsächlich ein kleines Skript unten erstellt, um dies zu überprüfen, und anscheinend kann SQLAlchemy externe Änderungen erkennen, ohne jedes Mal aufgerufen zu werden.

Danke,

P. S: Ich möchte wirklich verstehen, wie all die Magie hinter SQLAlchemy Arbeit geschehen. Hat jemand einen Zeiger auf einige Dokumente, die die Arbeit hinter den Kulissen von SQLAlchemy erklären?

import os 

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 

app = Flask(__name__) 

# Use SQLlite so this example can be run anywhere. 
# On Mysql, the same behaviour is observed 
basedir = os.path.abspath(os.path.dirname(__file__)) 
db_path = os.path.join(basedir, "app.db") 
app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///' + db_path 
db = SQLAlchemy(app) 


# A small class to use in the test 
class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(100)) 


# Create all the tables and a fake data 
db.create_all() 
user = User(name="old name") 
db.session.add(user) 
db.session.commit() 


@app.route('/') 
def index(): 
    """The scenario: the first request returns "old name" as expected. 
    Then, I modify the name of User:1 to "new name" directly on the database. 
    On the next request, "new name" will be returned. 
    My question is: how SQLAlchemy knows that the value has been changed? 
    """ 

    # Before, I always use db.session.commit() 
    # to make sure that the latest value is fetched. 
    # Without db.session.commit(), 
    # SQLAlchemy still can track change made on User.name 
    # print "refresh db" 
    # db.session.commit() 

    u = User.query.filter_by(id=1).first() 
    return u.name 


app.run(debug=True) 
+0

Die SQLAlchemy-Dokumente sind sehr, * sehr * gründlich und erwähnen auch externe Ressourcen. Hast du darüber nachgedacht, diese zu lesen, um zu verstehen, wie es funktioniert? – davidism

+0

Außerdem ist nicht klar, welches Problem Sie mit dem Code haben, den Sie gepostet haben. Bitte [bearbeiten], um ein [mcve] zu erstellen, das dein Problem * im Post selbst beschreibt *. – davidism

+0

hey danke für die Rückmeldung. Ich habe versucht, in SQLAlchemy doc zu suchen, aber habe nicht die Teile gefunden, die den Mechanismus hinter dieser "Magie" beschreiben. Vielleicht ist dies eine Technik, die von vielen ORM verwendet wird, so dass SQLAlchemy nicht darauf hinweisen muss? – Son

Antwort

4

Der „Cache“ einer Sitzung ist ein dict in seiner identity_map (session.identity_map.dict), die nur Objekte für die Zeit von „einem einzigen Geschäftsvorgang“ Caches, wie hier https://stackoverflow.com/a/5869795 beantwortet.

Für verschiedene Serveranforderungen haben Sie unterschiedliche identity_map. Es ist kein gemeinsames Objekt.

In Ihrem Szenario haben Sie den Server 2 getrennt angefordert. Beim zweiten Mal ist die identity_map eine neue (Sie können sie einfach durch Ausdrucken ihres Zeigers überprüfen) und hat nichts im Cache. Folglich wird die Sitzung die Datenbank anfordern und Ihnen die aktualisierte Antwort geben. Es ändert sich nicht, wie Sie vielleicht denken.

Also, auf Ihre Frage, brauchen Sie nicht session.commit() vor einer Abfrage zu tun, wenn Sie nicht eine Abfrage für das gleiche Objekt im gleichen Serveranfrage getan haben.

Hoffe es hilft.

+0

"Datensätze werden in der Identitätsübersicht für einen einzelnen Geschäftsvorgang gespeichert. Dies bedeutet, dass Sie unabhängig von der Konfiguration Ihres Webservers diese möglicherweise nicht länger als eine Anfrage aufbewahren (oder in der Sitzung speichern)." zitiert von http://stackoverflow.com/questions/5869514/sqlalchemy-identity-map-question/5869795#5869795 – Son