Reputation: 321
I recently updated Flask-SQLAlchemy, and now db.create_all
is raising RuntimeError: working outside of application context
. How do I call create_all
?
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///project.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
db.create_all()
This raises the following error:
Traceback (most recent call last):
File "/home/david/Projects/flask-sqlalchemy/example.py", line 11, in <module>
db.create_all()
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 751, in create_all
self._call_for_binds(bind_key, "create_all")
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 722, in _call_for_binds
engine = self.engines[key]
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 583, in engines
app = current_app._get_current_object() # type: ignore[attr-defined]
File "/home/david/Projects/flask-sqlalchemy/.venv/lib/python3.10/site-packages/werkzeug/local.py", line 513, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
Upvotes: 32
Views: 45945
Reputation: 437
If you are using a separate script to initialize the database, you can push a context manually.
Do not do this in the application module itself, only in a standalone script. If you push a context globally when setting up the application itself, it will not behave correctly.
# init_database.py
from myapp import app, db, Person
app.app_context().push()
db.create_all()
db.session.add_all([Person("A"), Person("B")])
db.session.commit()
Upvotes: 0
Reputation: 177
Here's an example.py
that configures a SQLite database, a model, then creates the database. The with app.app_context()
line around db.create_all()
is what's needed to avoid the context error.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
db = SQLAlchemy()
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
body = db.Column(db.String)
with app.app_context():
db.create_all()
Run the development server with this command, and the database will be created if it doesn't exist.
$ flask -A example.py --debug run
Upvotes: 9
Reputation: 93
If you're using a python
shell instead of flask shell
, you can push a context manually. flask shell
will handle that for you.
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Learn more about the application context in the Flask docs or this video.
Upvotes: 7
Reputation: 127310
As of Flask-SQLAlchemy 3.0, all access to db.engine
(and db.session
) requires an active Flask application context. db.create_all
uses db.engine
, so it requires an app context.
with app.app_context():
db.create_all()
When Flask handles requests or runs CLI commands, a context is automatically pushed. You only need to push one manually outside of those situations, such as while setting up the app.
Instead of calling create_all
in your code, you can also call it manually in the shell. Use flask shell
to start a Python shell that already has an app context and the db
object imported.
$ flask shell
>>> db.create_all()
Or push a context manually if using a plain python
shell.
$ python
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Upvotes: 82