Accessing app object from outside app context in Flask application
Setting up your app
Initializing your app
in the __init__
file of your project is very straightforward, but also very limited when the size of your project becomes bigger (and since you are using blueprints for your routes, I guess that the size of your project is big enough already).
The recommanded way of initializing your app
in this case is to use an App factory, which is basically a function that creates and returns the app
instance.
Here's a quick example of working arboresence (probably not the best one you will find, but that should do):
# myapp/application/setup.pyfrom flask import Flaskfrom .application.extensions import dbdef create_app(): app = Flask(__name__) app.config.from_object("myapp.config.Config") # Initialize extensions db.init_app(app) with app.app_context(): db.create_all() # Register Blueprints from myapp.player import player app.register_blueprint(player, url_prefix="/player/") return app
# myapp/application/extensions.pyfrom flask_sqlalchemy import SQLAlchemy# define global extensions in a separate file so that they can be imported from# anywhere else in the code without creating circular imports# the proper initialization is made within the `create_app` function db = SQLAlchemy()
# myapp/application/app.pyfrom .setup import create_appapp = create_app()
# myapp/__init__.pyfrom .application.app import app
# run.pyfrom myapp import appif __name__ == "__main__": app.run()
That's it for the hierarchy of your project. At this point, you have a myapp/application/app.py
that initialized the app
variable, and that you can import from anywhere you want without worrying about the import loops.
Checking headers before calling the view function
With the arboresence I suggested, and considering you update your imports accordingly, your decorator should now be working as expected.But what if I tell you Flask offers a way to do what you want, without implementing a decorator? This is where the before_request
kicks in.This is a special function you can write that will be called within the app-context before every single request on your application.
from myapp.application.app import app@app.before_requestdef require_apikey(): if request.headers.get("api-key") != API_KEY: abort(401, "Invalid API key")
Now the problem here is that this function will be called for every single endpoint you have defined, and maybe that's not what you want. But do not worry, you can also define a before_request
function to attach to a specific blueprint.
# myapp/my_blueprint.pyfrom myapp.tools import require_apikeymy_blueprint = Blueprint(...)my_blueprint.before_request = require_apikey