我对Flask很新,因为它的价值。我正在使用蓝图来分解我的代码,并尝试使用Flask-Assets来提供资产链接。但是出于某些原因,我无法让Flask-Assets在蓝图中工作。
代码结构:
/modules
/base
__init__.py
__init__.py
/static
# ... stuff
/templates
/layout.html
在/ 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')
基础布局中有这个:
{% assets "css_all" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" />
{% endassets %}
{% assets "js_all" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
实际上我现在在/modules/base/__init__.py中所拥有的内容甚至无法正常工作,因为它会抛出“RuntimeError:在应用程序上下文之外工作”。如果我将资产代码移动到索引函数中它确实有效,但每次我想添加资产时都必须重复该代码似乎很奇怪。有一个更好的方法吗?我错过了什么吗?
编辑 根据codecool的评论更新/modules/base/__init__.py,但现在它会抛出“TemplateSyntaxError:遇到未知标记'资产'”错误。我认为这是因为资产对象没有传递给应用程序。
编辑2: 因此,从SQLAlchemy的工作方式中获取一些建议,我得到了以下内容:
在我的主__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)
在base / __ init__.py中: 来自flask导入Blueprint,render_template,request 来自于flask.ext.assets导入环境,Bundle 来自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)
这里的技巧是在蓝图中创建资产,将其导入基本init,然后在那里调用.init_app。然而,在这种情况下,有两个蓝图就是这样做的。最后一个被称为总是胜出。也许有可能把它拉成一些常见的模块或什么......
答案 0 :(得分:7)
您无需在_get_current_object
上调用current_app
方法,这就是您收到错误的原因。 current_app
实际上是应用的代理。
代码应该是这样的:
app = current_app
assets = Environment(app)
事实上,您不需要将其指定为变量。这样做:
from flask import current_app as app
assets = Environment(app)
您收到RuntimeError,因为_get_current_object
仅在请求发生时可用,否则您必须使用current_app
。当您在index
视图中移动资源初始化代码时,它开始工作,就像现在在请求中一样。
_get_current_object
的用法来自Flask中的信号功能,您可以在此处阅读http://flask.pocoo.org/docs/signals/#sending-signals。
编辑:
这种情况正在发生,因为这不是初始化Flask资产的正确位置。它必须在modules/__init__.py
中初始化,其中在创建应用程序时设置jinja环境。
记住蓝图代码仅在访问时运行。所有全局初始化都应该在定义应用程序的模块中完成,即存在此代码的位置:
app = Flask(__name__)
assets = Environment(app)
答案 1 :(得分:0)
这里的技巧是在蓝图中创建资产,将其导入 base init,然后在那里调用 .init_app 。这打破的地方 然而,有两个蓝图可以做到这一点。最后一个 叫总是赢。也许有可能把它拉出来 一些通用模块什么的..
看看这篇文章。它很好地解释了如何使资产蓝图特定。 https://hackersandslackers.com/flask-assets/#blueprint-specific-bundles
您可以在任何地方声明捆绑包。在本文中,它们在单独的文件 assets.py
中声明。或者,您可以设置特定于蓝图的捆绑包,您可以在其中自行声明蓝图。然后将它们导入到您的主项目 __init__.py
文件中,并在您注册蓝图后注册它们。
我在这里修改了您的示例:
/__init__.py
:
from flask import Flask
from flask-assets import Environment
from modules.base import bp as base_bp, assets as base_assets
# Assuming more blueprints in addition to modules.base...
from modules.home import bp as home_bp, assets as home_assets
from modules.auth import bp as auth_bp, assets as auth_assets
# Declare Flask App
app = Flask(__name__)
# Register Blueprints
app.register_blueprint(base_bp)
app.register_blueprint(home_bp)
app.register_blueprint(auth_bp)
# Register Assets
bundles = {**base_assets, **home_assets, **auth_assets} # Combines all bundle-dictionaries into one
assets = Environment(app)
assets.register(bundles)
/modules/base/__init__.py
:
from flask import Blueprint, render_template
from flask-assets import Bundle
# Declare Blueprint
bp = Blueprint("base", __name__)
# Declare Blueprint-Specific Assets
bundles = {
"base_css": Bundle(
"base/css/bootstrap.min.css"
),
"base_js": Bundle(
"base/js/jquery-1.7.2.min.js",
"base/js/bootstrap.min.js"
)
}
@bp.route('/')
def index():
return render_template('index/index.html')
/modules/base/templates/layout.html
:
{% assets "base_css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" />
{% endassets %}
{% assets "base_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}