navy_green
navy_green

Reputation: 111

Flask: How can i use a context_processor from one blueprint in another blueprint

I create a context_process in blueprint apple,

apple > views.py

@apple.context_processor
def eat_apple():
    return dict(fruit='apple')

If i were in another blueprint, how would i access @apple.context_processor, so that I can use the variable when i render a template?

Upvotes: 3

Views: 4147

Answers (3)

sjoerd
sjoerd

Reputation: 47

Since I cannot reply to posts yet: I also was a bit struggling with this. My first solution worked but had some nasty side-effects with gunicorn.

What worked when using flask run, but what definitely will NOT WORK when using gunicorn or similar which is using multiple workers and your application is using ORM eg. sqlalchemy: In my create_app() I added the following lines (after blueprints got registered)

app.app_context().push()
from appserver.utils import context_processors

Although this works with gunicorn, I got weird behavior with database-mutations. Only mutation that were done in a specific worker would show up on the front-end, but when you navigate away and back the that page it might be entirely possible the page is served by a different worker. I do not exactly know how this works - apparently the session is tied to a worker and so "sees" only those changes.

What does work:

The changes I had the make (thanks for the hint @user885983) were quite easy now: In create_app() in replaced the lines above with the following and moved them where the other blueprints are being registered:

from appserver.utils import bp as utils_bp
app.register_blueprint(utils_bp)

and replaced @bp.context_processor with @bp.app_context_processor

I use this technique to load variables I need in all (jinja) templates like so (where backend is Class I created that handles a lot of common funtions:

@bp.app_context_processor
def get_menu_icons():
    menu_icon = backend.get_menu_icons()
    return dict(menu_icon=menu_icon)

This way I don't have to apply the variable to render_template() and still use it in the template: {{ menu_icon.delete }} eg.

Upvotes: 0

user885983
user885983

Reputation: 508

You can use Bluepint.app_context_processor

e.g.

bp = Blueprint("myblueprint", __name__, url_prefix=None)                               

@myblueprint.app_context_processor                                                        
def inject_template_globals():                                                   
    company = Company.query.first()                                              
    return dict(company=company)

Upvotes: 10

Ken Kinder
Ken Kinder

Reputation: 13120

Instead of assigning it to the blueprint, assign it to the app.

@app.context_processor
def eat_apple():
    return dict(fruit='apple')

The whole point of having a blueprint-local context processor is that it only operates on that blueprint. So if that's not what you want, put it on the app.

Upvotes: 7

Related Questions