9

我对 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:遇到未知标签‘assets’”错误。我认为这是因为资产对象没有传递到应用程序。

编辑 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 中: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)

这里的技巧是在蓝图中创建资产,将其导入基本 init,然后在那里调用 .init_app。然而,这失败的地方在于有两个蓝图可以做到这一点。最后一个叫的总是赢。也许可以将其拉出到某个通用模块或其他东西中..

4

2 回答 2

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 中的 Signals 功能,您可以在此处阅读有关它的信息http://flask.pocoo.org/docs/signals/#sending-signals

编辑:

发生这种情况是因为这不是初始化 Flask 资产的正确位置。它必须在modules/__init__.py创建应用程序时设置 jinja 环境的位置进行初始化。请记住,蓝图代码仅在访问时运行。所有全局初始化都应在定义您的应用程序的模块中完成,即存在此代码的位置:

    app = Flask(__name__)
    assets = Environment(app)
于 2012-07-09T05:36:21.110 回答
1

这里的技巧是在蓝图中创建资产,将其导入基本 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 %}
于 2021-01-04T16:36:20.673 回答