Reputation: 679
def get_db(self,dbfile):
if hasattr(g, 'sqlite_db'): self.close_db(g.sqlite_db)
try:
g.sqlite_db = self.connect_db('{}/{}'.format(app.root_path, dbfile))
except sqlite3.OperationalError as e:
raise e
return g.sqlite_db
Hi this code is located inside DB class, The error I get is
RuntimeError: working outside of application context
the error occurs on this line
g.sqlite_db = self.connect_db('{}/{}'.format(app.root_path, dbfile))
I think the problem is with g, it is imported like that from flask import g
How this error can be fixed? Thanks.
Upvotes: 57
Views: 198081
Reputation: 41
In my case, i had a flask application and i needed to call a method from my model to initialize the indexes to that db schema but that was not allowed in the model file and i needed to include in an url endpoint. Also i had different models and each model with different db, so connection query were also different. Therefore, what i did was:-
run.py
from config import Config, app_config
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run(debug = app_config.DEBUG, port = Config.PORT)
app/__init __.py
from flask import Flask
from config import Config
from app.blueprints import all_blueprints
def create_app():
app = Flask(__name__)
app.config.from_object('config.Config')
# Registering allowed service blueprints
for blueprint in all_blueprints:
app.register_blueprint(blueprint)
return app
app/models/User.py
See the with app.app_context():
from config import Config
from flask_pymongo import PyMongo
from flask import Flask, current_app
app = Flask(__name__)
mongo = PyMongo(app, uri = 'mongodb://localhost:27017/database1')
class UserMaster:
def __init__(self, uid, user_id, user_name, password):
self.user_id = user_id
self.user_name = user_name
self.password = password
@classmethod
def from_dict(cls, data):
return cls(
user_id=data.get('user_id'),
user_name=data.get('user_name'),
password=data.get('password'),
)
@staticmethod
def find_by_id(type, user_id):
user_data = mongo.db.UserMaster.find_one({type: user_id})
if user_data:
return user_data
return None
@staticmethod
def create_indexes(mongo):
mongo.db.UserMaster.create_index([('user_id', 1)], unique=True)
return UserMaster
with app.app_context():
UserMaster.create_indexes(mongo)
app/blueprints/auth/login_bp.py
from config import Config
from flask_pymongo import PyMongo
from app.models.UserMaster import UserMaster
from flask import Blueprint, jsonify, request, current_app
login_bp = Blueprint('login_bp', __name__)
# LOGIN ENDPOINT
@login_bp.route('/login', methods=['POST'])
def login():
data = request.get_json()
id = data.get("login_id")
encrypted_password = data.get("login_password")
user = UserMaster.find_by_id(login_id_type, id)
if user:
response_data = {"status": "success"}
return jsonify(response_data), 200
and this allowed me to extend the context of flask
Upvotes: 0
Reputation: 41
I tested different solutions and here are the results:
When we type python in the terminal and then Enter, or python3 and Enter, unfortunately everything does not work as it should.
The solution is to type flask shell. This is what flask shell does - that's what you should use!
So:
Result:
flask shell
db.create_all()
from app import db, Customer
person = Customer.query.filter_by(id=1).first()
person.first_name
where:
Upvotes: 1
Reputation: 11
>>> from app import app, db
>>> app.app_context().push()
>>> db.create_all()
In my case, it worked.
Upvotes: 1
Reputation: 19
From terminal type: python or python3
>>>from app import app, db
>>>app.app_context().push()
>>>db.create_all()
Upvotes: 1
Reputation: 101
This is what fixed it for me. I hope it helps someone else.
if __name__ == "__main__":
with app.app_context():
db.create_all()
app.run(debug=True)
Upvotes: 9
Reputation: 9
when creating an app just add the below code.
app = Flask(__name__)
app.app_context().push()
Upvotes: -1
Reputation: 799
When initializing the app I use this block instead :
def create_app():
app = Flask(__name__)
with app.app_context():
init_db()
return app
Upvotes: 1
Reputation: 1
Install this version of flask using
pip install flask-sqlalchemy==2.5.1
then run db.create_all()
and it will run.
Upvotes: -3
Reputation: 431
First method
flask shell
, thendb.create_all()
Second method
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()
.
Open the python terminal in your project directory and manually add a context
from project_name import app, db
app.app_context().push()
db.create_all()
Upvotes: 31
Reputation: 49
Use
pip install flask-sqlalchemy==2.5.1
This might solve the error
Upvotes: 3
Reputation: 671
Please check out the Purpose of context
#filename = run.py (inside root directory)
from flaskblog import create_app
app = create_app()
if __name__ == "__main__":
app.run(debug=True)
filename = __init __.py (inside flaskblog folder)
app = Flask(__name__)
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = "users.login"
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
from flaskblog.user.routes import users
app.register_blueprint(users)
return app
filename = config.py (inside flaskblog folder)
class Config:
SECRET_KEY = 'your secret key'
SQLALCHEMY_DATABASE_URI = 'your db uri'
filename = models.py
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
users folder (inside flaskblog)
users folder contain one __init__.py file
Filename = form.py (inside users folder)
class LoginForm(FlaskForm):
# define your field
pass
Filename = routes.py (inside users folder)
users = Blueprint('users',__name__)
@users.route('/login', methods=['GET', 'POST'])
def login():
# do your stuff
pass
Upvotes: 4
Reputation: 2638
Other users have pointed out how to solve the immediate problem, however you might consider modifying how the database connection is created to solve this issue.
Instead of having a method within you DB class instantiate the database connection you could have the connection created in the controller before every request. Then use the teardown_request decorator to close the connection.
Then when within a route you could pass the connection to the DB class as part of instantiating a new DB object.
This would ensure that you never create a database connection unless you need one. And it prevent you from accessing Flask globals out of the app context.
@app.before_request
def before_request():
try:
g.sqlite_db = self.connect_db('{}/{}'.format(app.root_path, dbfile))
except sqlite3.OperationalError as e:
raise e
@app.teardown_request
def teardown_request(e):
if hasattr(g, 'sqlite_db'): self.close_db(g.sqlite_db)
@app.route('/someroute', methods=["GET"]:
def someroute():
db_obj = DB(g.sqlite_db)
.
.
.
Upvotes: 4
Reputation: 1022
I had the same issue while doing some unit testing.
Adding the following function to my test class solved my issue:
@classmethod
def setUpClass(self):
self.app = create_app("testing")
self.client = self.app.test_client()
Upvotes: 0
Reputation: 3217
To expand on @VadimK's answer. If you want to prevent your code from executing outside of an app_context
you can use flask.has_app_context() to see if the code is currently inside an app context:
See also: flask.has_request_context()
Upvotes: 3
Reputation: 605
Maybe you need to call your function inside an application context:
with app.app_context():
# call your method here
Upvotes: 51
Reputation: 550
When creating your app, use:
app.app_context().push()
for example like this:
from yourapp import create_app
app = create_app()
app.app_context().push()
Upvotes: 42
Reputation: 1
ERROR:This typically means that you attempted to use functionality that needed to interface with the current application object in a way. To solve this set up an application context with app.app_context(). See the documentation for more information.
Upvotes: -34
Reputation: 1220
From the Flask source code in flask/globals.py
:
_app_ctx_err_msg = '''\
Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in a way. To solve
this set up an application context with app.app_context(). See the
documentation for more information.\
'''
Following the documentation, you can see that you need to make flask.current_app
point to your application and it currently doesn't.
You're probably calling your DB function before Flask has initialized. My guess is that your app
object has not been created yet with the Flask
constructor.
Upvotes: 27