【问题标题】:Flask: get the context on the filterFlask:获取过滤器的上下文
【发布时间】:2020-11-13 08:49:58
【问题描述】:

我是flask的初学者,我想练习filter,我看过官方的documentation,但是没有用。

我想创建一个firstof 过滤器,即输出第一个不为“false”的参数变量。(与Django 的firstof 相同)。

<h1>Hi, {{ "username, 'guest'"| firstof }} </h1>
@app.route('/')
def index():
    return render_template('index.html')  # expect output: Hi, guest
    # return render_template('index.html', username='Carson')  # Hi, Carson

我试试,

@app.template_filter('firstof')
def firstof_filter(s: str):
    """
    USAGE::

        {{ "var1, var2, 'default_val'" | firstof }}
    """
    for data in s.split(','):
        data = data.strip()
        if data[0] == data[-1] and data[0] in ("'", '"'):
            return data[1:-1]  # a constant
        """ # does any similar grammar like below?
        if hasattr(app.current.context, data):
            return app.current.context[data]
        """

如果您能提供更多关于烧瓶过滤器的链接,那就太好了。谢谢!

【问题讨论】:

    标签: python-3.x django flask


    【解决方案1】:

    我自己找到了答案。

    直接用 Flask 来实现并不容易。

    因为

    # flask.templating.py
    
    def render_template(template_name_or_list, **context):
        ctx = _app_ctx_stack.top
        ctx.app.update_template_context(context)  # it does not store the context in the ctx. it just adds something to the context
        return _render(
            ctx.app.jinja_env.get_or_select_template(template_name_or_list),
            # ctx.app.jinja_env is an environment (It combined Flask and Jinja, pretty like the Jinja.Environment)
            # get_or_select_template, will run our function and no passing the context so that is why it so hard to do it.
            context,
            ctx.app,
        )
    
    def _render(template, context, app):
        # It seems we can't do anything when the process already here.
        before_render_template.send(app, template=template, context=context)
        rv = template.render(context)
        template_rendered.send(app, template=template, context=context)
        return rv
    

    但我们得到一个线索,我们可以更改Jinja.Environment

    您可以在继续之前先引用Custom Filters

    解决方案和演示

    from flask import render_template
    from jinja2 import contextfilter
    from flask.helpers import locked_cached_property
    from flask import Flask
    from jinja2.runtime import Context
    from flask.templating import Environment
    from typing import Dict
    from pathlib import Path
    
    @contextfilter
    def firstof_filter(ctx: Context, s: str):
        ctx: Dict = ctx.parent
        for data in s.split(','):
            data = data.strip()
            if data[0] == data[-1] and data[0] in ("'", '"'):
                return data[1:-1]  # a constant
            if data in ctx:
                return ctx[data]
    
    class MyFlask(Flask):
        @locked_cached_property
        def jinja_env(self):
            env: Environment = self.create_jinja_environment()
            env.filters['firstof'] = firstof_filter  # well, this way is not smart, you are better build a register to get all the filters that you have defined.
            return env
    
    app = MyFlask(__name__, template_folder=Path('./templates'))
    
    
    @app.route('/')
    def test():
        return render_template('test.html', username='Carson') + '\n' + render_template('test.html')
    
    
    app.run(debug=True)
    

    在哪里 test.html

    <h1>Hi, {{ "username, 'guest'"| firstof }} </h1>
    

    附言

    env.filters['firstof'] = firstof_filter嗯,这种方式不聪明。你最好建立一个注册来获取你定义的所有过滤器。

    您可以参考Django:django.template.library.py -&gt; class Library收集所有filters...

    输出

    Hi, Carson
    Hi, guest
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      相关资源
      最近更新 更多