working outside of application context – Flask

Question:

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.

Asked By: Koten

||

Answers:

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.

Answered By: Juan Pablo Santos

Maybe you need to call your function inside an application context:

with app.app_context():
  # call your method here
Answered By: VadimK

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.

Answered By: Linden

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()

for further information

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()

Answered By: user2682863

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()
Answered By: Cyrus

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)
    .
    .
    .
Answered By: steve

Simple Example To Avoid This Error

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)

Inside flaskblog folder

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
Answered By: Azhar Uddin Sheikh

Use

pip install flask-sqlalchemy==2.5.1

This might solve the error

Answered By: Mehul Batra

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)
Answered By: Nadeem

Two possible solution

First method

  1. Instead of calling create_all() in your code, call manually in the flask shell which is CLI
  • Go to your terminal
  1. type flask shell, then
  2. db.create_all()

Second method

  1. As it says in the runtime error message

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()

Check out this video for better understanding.

YouTube Video

Answered By: Yohanes Getient

Install this version of flask using

pip install flask-sqlalchemy==2.5.1

then run db.create_all() and it will run.

Answered By: Tasi

When initializing the app I use this block instead :

def create_app():
app = Flask(__name__)

with app.app_context():
    init_db()

return app
Answered By: Dyo Medio

when creating an app just add the below code.

app = Flask(__name__)
app.app_context().push()
Answered By: Rehman Khan

app = Flask(name)
app.app_context().push()

Answered By: Rishikesh Sonawane
  1. Import project as file application name and database; e.q.file name is app.py
  2. Create app context
  3. Create data base

From terminal type:
python or python3

>>>from app import app, db
>>>app.app_context().push()
>>>db.create_all()
Answered By: Adi H.
>>> from app import app, db
>>> app.app_context().push()
>>> db.create_all()

In my case, it worked.

Answered By: user22283920

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:

  1. flask shell
  2. db.create_all()
  3. …your code…

Result:

flask shell
db.create_all()
from app import db, Customer
person = Customer.query.filter_by(id=1).first()
person.first_name

where:

  • my app = app.py
  • my db = db
  • my table = Customer
  • my object = person
  • my column in table Customer = first_name
Answered By: Aleksander Szycik

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

Answered By: prajwal tulawe
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.