title: Does db.session.commit change app context in Flask-SQLAlchemy?
body: <p>I am configuring a fixture for pytest that creates a flask app instance. My app is created with <a href="http://flask.pocoo.org/docs/0.12/patterns/appfactories/" rel="nofollow noreferrer">Application Factories pattern</a>. I am at the stage of connecting it to the database and struggle to understand the difference between 2 patterns.</p>
  
  <pre><code># project/__init__.py
  import os
  from flask import Flask
  from flask_sqlalchemy import SQLAlchemy
  
  
  db = SQLAlchemy()
  
  
  def create_app():
      app = Flask(__name__)
  
      app_settings = os.getenv('APP_SETTINGS')
      app.config.from_object(app_settings)
  
      db.init_app(app)
  
      [blueprint code]
  
      return app
  </code></pre>
  
  <p>In my fixture, I think I understand the need for: </p>
  
  <ul>
  <li><code>db.create_all()</code> during setup: create my tables</li>
  <li><code>db.drop_all()</code> during teardown: clean database after tests</li>
  <li><code>db.session.remove()</code> during teardown: avoid some weird locks on postgres when hitting the database frequently in tests</li>
  </ul>
  
  <p>The first setup (inspired by <a href="https://flaskbook.com/#" rel="nofollow noreferrer">Miguel Grinberg book</a>) makes sense to me: </p>
  
  <pre><code>import pytest
  from project import create_app, db
  
  
  @pytest.fixture
  def app():
      app = create_app()
      with app.app_context():
          db.create_all()
          yield app
          db.session.remove()
          db.drop_all()
  </code></pre>
  
  <p>It also matches the behavior I get in an interactive session, where I need to activate/push the <code>app_context</code> to bind the database:</p>
  
  <pre><code>Python 3.6.1 (default, Jun 21 2017, 18:45:41) 
  [GCC 4.9.2] on linux
  Type "help", "copyright", "credits" or "license" for more information.
  &gt;&gt;&gt; from project import create_app, db
  &gt;&gt;&gt; app = create_app()
  &gt;&gt;&gt; db
  &lt;SQLAlchemy engine=None&gt;
  &gt;&gt;&gt; app_ctx = app.app_context()
  &gt;&gt;&gt; app_ctx.push()
  &gt;&gt;&gt; db.create_all()
  &gt;&gt;&gt; db
  &lt;SQLAlchemy engine='postgres://postgres:postgres@users-db:5432/users_dev'&gt;
  </code></pre>
  
  <p>The second setup (inspired by <a href="http://testdriven.io/part-one-test-setup/" rel="nofollow noreferrer">testdriven.io</a>) also work in pytest but I don't know why:</p>
  
  <pre><code>import pytest
  from project import create_app, db
  
  
  @pytest.fixture
  def app():
      app = create_app()
      db.create_all()
      db.session.commit()  # fail when this is removed
      yield app
      db.session.remove()
      db.drop_all()
  </code></pre>
  
  <p>Actually, if I try to do the same in an interactive session, I get an error:</p>
  
  <pre><code>Python 3.6.1 (default, Jun 21 2017, 18:45:41) 
  [GCC 4.9.2] on linux
  Type "help", "copyright", "credits" or "license" for more information.
  &gt;&gt;&gt; from project import create_app, db
  &gt;&gt;&gt; app = create_app()
  &gt;&gt;&gt; db.create_all()
  [...] timeError: application not registered on db instance and no application bound to current context
  </code></pre>
  
  <p>I tried to run the fixture without <code>db.session.commit()</code>, thinking that maybe I was in the app context by default (similar to what I do with <code>with app_context()</code> in the first fixture). But it fails if I remove it.</p>