Blueprint-specific assets in Flask using Flask-Assets?


Question

I'm pretty new to Flask, for what it's worth. I'm using blueprints to break up my code and am trying to use Flask-Assets for serving up asset links. For some reason, though, I can't get Flask-Assets to work within a blueprint.

Code structure:

/modules
    /base
        __init__.py
    __init__.py
/static
    # ... stuff
/templates
    /layout.html

In /modules/base/__init__.py:

from flask import Blueprint, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.assets import Environment, Bundle
from flask import current_app as app

default = Blueprint('base', __name__)

assets = Environment(app)

css = Bundle('css/bootstrap.min.css')
assets.register('css_all', css)

js = Bundle('js/jquery-1.7.2.min.js', 'js/bootstrap.min.js')
assets.register('js_all', js)

@default.route('/')
def index():

    return render_template('index/index.html')

And the base layout has this in it:

{% assets "css_all" %}
    <link rel="stylesheet" href="{{ ASSET_URL }}" />
{% endassets %}
{% assets "js_all" %}
    <script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}

Actually what I have in /modules/base/__init__.py right now doesn't even work, as it throws "RuntimeError: working outside of application context". If I move the assets code into the index function it does work, but it seems weird to have to repeat that code every time I want to add assets. Is there a better way to do this? Am I missing something?

Edit: Updated /modules/base/__init__.py per codecool's comment, but now it throws an "TemplateSyntaxError: Encountered unknown tag 'assets'" error. I think this one is because the assets object isn't getting passed through to the app.

Edit 2: So taking some advice from how SQLAlchemy does things, I got this to sort of work with the following:

In my main __init__.py:

from flask import Flask
from modules.base import default, assets as base_assets
from flask.ext.assets import Environment, Bundle

app = Flask(__name__) 
app.register_blueprint(default)

base_assets.init_app(app)

In base/__init__.py: from flask import Blueprint, render_template, request from flask.ext.assets import Environment, Bundle from flask import current_app as app

default = Blueprint('base', __name__)

assets = Environment(app)

css = Bundle('css/bootstrap2.min.css')
assets.register('css_all', css)

js = Bundle('js/jquery-1.7.2.min.js', 'js/bootstrap.min.js')
assets.register('js_all', js)

The trick here is creating assets in the blueprint, importing it into the base init, and then calling .init_app there. Where this breaks down, however, is in having two blueprints that do this. The last one called always wins out. Maybe it'd be possible to pull this out into some common module or something..

1
7
7/11/2012 3:03:27 AM

You dont need to call _get_current_object method on current_app and thats why you are getting the error. current_app is actually a proxy for the app. Code should be like this:

    app = current_app
    assets = Environment(app)

Infact, you don't need to assign it as variable. Do this:

     from flask import current_app as app

     assets = Environment(app)

You are getting RuntimeError because _get_current_object is available only when a request is going on otherwise you have to use current_app. When you moved assets initializing code inside the index view then it started working as it was now inside a request.

_get_current_object's usage comes in Signals functionality in Flask and you can read about it here http://flask.pocoo.org/docs/signals/#sending-signals.

Edit:

This is happening because this is not the right place to initialize Flask assets. It has to be initialized in modules/__init__.py where jinja environment is set up when app is created. Remember blueprints code is run only when it is accessed. All the global initializations should be done in the module where your app is defined i.e where this code is present:

    app = Flask(__name__)
    assets = Environment(app)
7
7/10/2012 6:54:42 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon