Thursday, 2 February 2023

Getting 'RuntimeError: Working outside of application context.' when trying to import function from another Blueprint

Initial Notes: The project uses Blueprints and below are the file structure and extracts of the code used...

File Structure:

/app
├── flaskapp/
│   ├── posts/
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── routes.py
│   │   ├── utils.py
│   ├── users/
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── routes.py
│   │   ├── utils.py
│   ├── main/
│   │   ├── __init__.py
│   │   ├── crons.py
│   │   ├── routes.py
│   ├── templates/
│   │   ├── users.html
│   ├── __init__.py
│   ├── config.py
│   ├── models.py
├── run.py

posts/utils.py

# Function to get all posts from DB

def get_all_posts():
    post = Post.query.order_by(Post.id.asc())
    return post

users/routes.py

# Importing 'get_all_posts' function from 'posts/utils.py'

from flaskapp.posts.utils import get_all_posts



users = Blueprint('users', __name__)


#All Users Route + Related Posts

@posts.route("/posts", methods=['GET'])
@login_required
def all_users():
    users = User.query.order_by(User.id.asc())
    return render_template('users.html', USERS=users, POSTS=get_all_posts())

main/crons.py

# Importing 'get_all_posts' function from 'posts/utils.py'

from flaskapp.posts.utils import get_all_posts


# A function to be called using 'scheduler' from 'flaskapp/__init__.py' on launch

def list_expired_posts():
    posts = get_all_posts()
    for p in posts:
        if p.expired == 1:
            print(p.title)

scheduler = BackgroundScheduler()
scheduler.add_job(func=list_expired_posts, trigger="interval", seconds=60)
scheduler.start()


# Terminate Scheduler on APP termination

atexit.register(lambda: scheduler.shutdown())

flaskapp/init.py

# __init__.py Main

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flaskapp.config import Config

db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = 'users.login'
login_manager.login_message_category = 'warning'


# Create APP Function
def create_app(config_class=Config):
    app = Flask(__name__)
    # Import Configuration from Config File Class
    app.config.from_object(Config)

    db.init_app(app)
    login_manager.init_app(app)

    # Import Blueprint objects
    from flaskapp.posts.routes import posts
    from flaskapp.users.routes import users
    from flaskapp.main.routes import main
    
    # Register Blueprints
    app.register_blueprint(posts)
    app.register_blueprint(users)
    app.register_blueprint(main)
    # END

    return(app)

# Calling scheduler function 'list_expired_posts' FROM '/main/crons.py' as a scheduled job to be triggered on app initiation

from flaskapp.main.crons import list_expired_posts
list_expired_posts()

Explanation:

I have the function 'get_all_posts()' located in 'posts/utils.py' which works fine when I import it and use it in another blueprint's routes.py file (ex.** users/routes.py**) as shown above.

But I'm getting the below error when importing the same function in another blueprint (specifically.** main/crons.py**) as shown above.

I'm trying to use the 'get_all_posts()' function from 'posts/utils.py' within the 'list_expired_posts()' in 'main/crons.py' and then calling the 'list_expired_posts()' function from 'flaskapp/init.py' to trigger it on launch and keep on executing it every 60 minutes.

Error:

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.

*Conclusion Notes + Steps attempted: *

I have already eliminated the 'Scheduler' temporarily and tried working only with the function itself and not even calling it from 'flaskapp/init.py'.


I have also tried moving the below code to the 'def create_app(config_class=Config)' section without any luck

from flaskapp.main.crons import list_expired_posts
list_expired_posts()

I have also tried creating a specific Blueprint for 'crons.py' and registering it to my 'flaskapp/init.py' but still got the same result.


As a final outcome, I am trying to call the 'get_all_posts()' FROM 'posts/utils.py', then filter out the 'expired posts' using the 'list_expired_posts()' function FROM 'main/crons.py' and schedule it to print the title of the expired posts every 60 minutes.

Since I've eliminated the scheduler already to test out, I'm quite sure this is not a scheduler issue but some import mixup I'm not figuring out.


I am also aware that the 'list_expired_posts()' can become as another function in 'posts/utils.py' and then directly call the function from there using the scheduler which I've also tried but keep getting the same error.


I also tried manually configuring the app's context as instructed in other posts but I keep getting the same error.

with app.app_context():

I'm not really a Python pro and I always try seeking multiple online resources prior to posting a question here but it seems like i'm out of luck this time. Your help is truly appreciated.



from Getting 'RuntimeError: Working outside of application context.' when trying to import function from another Blueprint

No comments:

Post a Comment