1

I'm trying to write a cache module using Flask and Flask-migrate. I get the following error:

Traceback (most recent call last):
  File "manage.py", line 7, in <module>
    migrate = Migrate(current_app, db)
  File "F:\gog-cache\venv\lib\site-packages\flask_migrate\__init__.py", line 49, in __init__
    self.init_app(app, db, directory)
  File "F:\gog-cache\venv\lib\site-packages\flask_migrate\__init__.py", line 55, in init_app
    if not hasattr(app, 'extensions'):
  File "F:\gog-cache\venv\lib\site-packages\werkzeug\local.py", line 348, in __getattr__
    return getattr(self._get_current_object(), name)
  File "F:\gog-cache\venv\lib\site-packages\werkzeug\local.py", line 307, in _get_current_object
    return self.__local()
  File "F:\gog-cache\venv\lib\site-packages\flask\globals.py", line 52, in _find_app
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.

Here's my code:

app.py

import os
from flask import Flask


def create_app(config=os.environ['GOG_CACHE_APP_SETTINGS']):
    app = Flask(__name__)
    app.config.from_object(config)
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    with app.app_context():
        register_extensions(app)
        from cache import cache
        app.register_blueprint(cache)
    app.app_context().push()

    return app


def register_extensions(app):
    from extensions import db
    db.init_app(app)


if __name__ == '__main__':
    app = create_app()
    app.run()

manage.py

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from flask import current_app
from extensions import db


migrate = Migrate(current_app, db)
manager = Manager(current_app)

manager.add_command('db', MigrateCommand)


if __name__ == '__main__':
    manager.run()

extensions.py

from flask_sqlalchemy import SQLAlchemy
from rq import Queue
from worker import conn


db = SQLAlchemy()
q = Queue(connection=conn)

I execute the following command:

python manage.py db migrate

I tried moving Migrate and Manage objects from manage.py to extensions.py with no success. I also tried to put them in with current_app.app_context(). Unfortunately it doesn't make the error disappear.

What are other ways to ensure that the objects have access to the context?

EDIT: It looks that the error arises because current_app is not available the time I execute the script. I found a workaround but it seems dirty to me. I updated manage.py to import app factory instead of current_app:

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from extensions import db
from app import create_app

app = create_app()
migrate = Migrate(app, db)
manager = Manager(app)

manager.add_command('db', MigrateCommand)


if __name__ == '__main__':
    manager.run()

Is there any other (possibly cleaner) solution?

izdwuut
  • 11
  • 3
  • This is the correct way to do it, why do you think it is dirty? How did you expect that `current_app` will be set to an application instance in your original version of the code? – Miguel Grinberg Jan 28 '20 at 23:42
  • @Miguel I just thought that the correct way would be use `current_app` in some way, but I guess that you're right. I'm new to to Flask and I had troubles grasping my head around it. – izdwuut Jan 29 '20 at 17:15
  • The important thing to remember is that `current_app` isn't really smart, it does not know what the app is unless you set it yourself by installing an app context, or else you are inside a request handler, in which case Flask itself sets the app context. – Miguel Grinberg Jan 29 '20 at 18:35

0 Answers0