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.
/modules /base __init__.py __init__.py /static # ... stuff /templates /layout.html
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:
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..
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.
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)