使用Flask-Assets在Flask中使用特定于蓝图的资产?

时间:2012-07-09 04:01:41

标签: python flask

我对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。然而,在这种情况下,有两个蓝图就是这样做的。最后一个被称为总是胜出。也许有可能把它拉成一些常见的模块或什么......

2 个答案:

答案 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 %}