Flask - SubViews

时间:2013-07-10 04:53:48

标签: python flask

我希望在我的应用程序中使用某种设计模式,但我不确定我的模式是否真的适合Flask机制。我只是在核实我没有忽视现有的解决方案。

我希望有一个顶级视图,用于呈现另一个代理请求的响应。问题是,我不是代理外部URL,而是代理同一个应用程序中的视图(类似于依赖于其他蓝图的蓝图)。与'render_template()'函数类似,我正在寻找像render_view,甚至更好,*request_view_as_string*的东西。然后我需要处理响应并重新渲染。

我尽可能使用模板继承(jinja2),但我的很多困难来自于模板块之间的大量非模板处理。我仍然感觉到了jinja,我的模板开始感觉被黑客污染了。


修改

基本上,我误解了jinja的角色。我的应用程序需要在jinja上加重。我一直试图尽快进出jinja,这就是我的嵌套依赖开始引起问题的地方。最终,我的“子视图”所需的大多数功能都是内置于Jinja中的,我只是不确定如何将它们与FLask正确集成。

2 个答案:

答案 0 :(得分:2)

首先,Jinja2支持macros,它允许您在模板之间共享功能:

{# helpers.jinja #}
{% macro generate_select(itrbl) %}
    <select{{kwargs|xmlattrs}}>
    {% for item in itrbl %}
        <option value="{{item.value}}">{{item.text}}</option>
    {% endfor %}
    </select>
{% endmacro %}

{# page1.jinja #}
{% import "helpers.jinja" as helpers %}
{{ helpers.generate_select(data, name="my_data_field") }}

对于更复杂的功能(A / B测试,根据用户帐户启用的内容加载不同功能等),extendsincludeimport可以变量值:

{# A custom template with a *lot* of hooks #}
{% extends base_template %}
{% import custom_functionality_provider as provider %}
{% block common_name %}
    {% if features.feature_x %}
        {% include feature_x_include %}
    {% endif %}
    {{ provider.operation() }}
{% endblock common_name %}

@app.route("/some-route")
def some_route():
    # Of course, in real life you would determine these values
    # on the basis of user / condition lookups, rather than
    # hardcoding values in your render_template call
    render_template("custom.jinja", base_template="AB/A/base.jinja",
        custom_functionality_provider="macros/lowcostplan.jinja",
        feature_x_include="AB/A/features/feature_x.jinja",
        features=some_features_object)

最后,您可以将返回字符串的callables传递给任何Jinja模板,让您获得Python的全部功能:

def custom_implimentation_a(**context_args):
    return render_template("template_a.jinja", **context_args)

def custom_implimentation_b(**context_args):
    return render_template("template_b.jinja", **context_args)

@app.route("/some-route")
def some_route():
    if condition:
        provider = custom_implimentation_a  # Note, no parenthesis
    else:
        provider = custom_implimentation_b

    return render_template("some_page.jinja", provider=provider)

答案 1 :(得分:0)

我认为Sean的第一个答案是最合适的,但是当Jinja使Python任务有点困难的时候,我确实碰到了这个小机制。

http://werkzeug.pocoo.org/docs/local/

这应该比Flask的g变量更有效率。另请参见略有不同的用法(当一个全局“命名空间”不再可管理时)

http://flask.pocoo.org/snippets/13/

我经常忘记Flask和Werkzeug是相关的项目。这样做的巨大好处是它们的大部分功能都与其他项目不重叠。

当你从Flask那边接近新手时,如果你觉得Flask缺少一些齿轮,那很有可能是因为他们已经将它们包含在Werkzeug中了。