title: How does SQLAlchemy track database changes?
body: <p>I wonder how SQLAlchemy tracks changes that are made outside of SQLAlchemy (manual change for example)? </p>
  
  <p>Until now, I used to put <code>db.session.commit()</code> before each value that can be changed outside of SQLAlchemy. Is this a bad practice? If yes, is there a better way to make sure I'll have the latest value? I've actually created a small script below to check that and apparently, SQLAlchemy can detect external changes without <code>db.session.commit()</code> being called each time.</p>
  
  <p>Thanks,</p>
  
  <p>P.S: I really want to understand how all the magics happen behind SQLAlchemy work. Does anyone has a pointer to some docs explaining the behind-the-scenes work of SQLAlchemy?</p>
  
  <pre><code>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)
  </code></pre>