首页 文章

从jinja2调用python函数

提问于
浏览
110

我正在使用jinja2,我想调用一个python函数作为帮助器,使用类似的语法,就好像我调用一个宏 . jinja2似乎打算阻止我进行函数调用,并坚持通过将函数作为宏复制到模板中来重复自己 .

有没有直接的方法来做到这一点?并且,有没有办法导入一整套python函数并让它们可以从jinja2访问,而不需要经历大量的繁琐(例如编写扩展)?

11 回答

  • 32

    对于使用Flask的人,请将其放在 __init__.py 中:

    def clever_function():
        return u'HELLO'
    
    app.jinja_env.globals.update(clever_function=clever_function)
    

    并在您的模板中使用 {{ clever_function() }} 调用它

  • 7

    Note: This is Flask specific!

    我知道这篇文章很老了,但是在使用上下文处理器的Flask的新版本中有更好的方法 .

    Variables can easily be created:

    @app.context_processor
    def example():
        return dict(myexample='This is an example')
    

    以上可以在带有Flask的Jinja2模板中使用,如下所示:

    {{ myexample }}
    

    (哪个输出 This is an example

    As well as full fledged functions:

    @app.context_processor
    def utility_processor():
        def format_price(amount, currency=u'€'):
            return u'{0:.2f}{1}'.format(amount, currency)
        return dict(format_price=format_price)
    

    以上使用时如下:

    {{ format_price(0.33) }}
    

    (使用货币符号输出输入价格)

    Alternatively, you can use jinja filters, baked into Flask. E.g. using decorators:

    @app.template_filter('reverse')
    def reverse_filter(s):
        return s[::-1]
    

    或者,没有装饰器,并手动注册该功能:

    def reverse_filter(s):
        return s[::-1]
    app.jinja_env.filters['reverse'] = reverse_filter
    

    使用上述两种方法应用的过滤器可以像这样使用:

    {% for x in mylist | reverse %}
    {% endfor %}
    
  • 190

    我认为jinja故意难以在模板中运行'任意'python . 它试图强化这样的观点,即模板中较少的逻辑是一件好事 .

    您可以在 Environment 实例中操作全局命名空间以添加对函数的引用 . 必须在加载任何模板之前完成 . 例如:

    from jinja2 import Environment, FileSystemLoader
    
    def clever_function(a, b):
        return u''.join([b, a])
    
    env = Environment(loader=FileSystemLoader('/path/to/templates'))
    env.globals['clever_function'] = clever_function
    
  • 102
    from jinja2 import Template
    
    def custom_function(a):
        return a.replace('o', 'ay')
    
    template = 'Hey, my name is {{ custom_function(first_name) }}'
    jinga_html_template = Template(template)
    jinga_html_template.globals['custom_function'] = custom_function
    
    fields = {'first_name': 'Jo'}
    print jinga_html_template.render(**fields)
    

    将输出:

    Hey, my name is Jay
    

    适用于Jinja2版本2.7.3

  • 0

    使用lambda将模板连接到主代码

    return render_template("clever_template", clever_function=lambda x: clever_function x)
    

    然后,您可以在模板中无缝调用该函数

    {{clever_function(value)}}
    
  • 0

    我喜欢@AJP's answer . 我逐字地使用它,直到我结束了很多功能 . 然后我切换到Python function decorator .

    from jinja2 import Template
    
    template = '''
    Hi, my name is {{ custom_function1(first_name) }}
    My name is {{ custom_function2(first_name) }}
    My name is {{ custom_function3(first_name) }}
    '''
    jinga_html_template = Template(template)
    
    def template_function(func):
        jinga_html_template.globals[func.__name__] = func
        return func
    
    @template_function
    def custom_function1(a):
        return a.replace('o', 'ay')
    
    @template_function
    def custom_function2(a):
        return a.replace('o', 'ill')
    
    @template_function
    def custom_function3(a):
        return 'Slim Shady'
    
    fields = {'first_name': 'Jo'}
    print(jinga_html_template.render(**fields))
    

    好东西有 __name__

  • 68

    从来没有在官方文档或堆栈溢出时看到这么简单的方式,但是当发现这个时我很惊讶:

    # jinja2.__version__ == 2.8
    from jinja2 import Template
    
    def calcName(n, i):
        return ' '.join([n] * i)
    
    template = Template("Hello {{ calcName('Gandalf', 2) }}")
    
    template.render(calcName=calcName)
    # or
    template.render({'calcName': calcName})
    
  • 6

    要从Jinja2调用python函数,您可以使用与globals类似的自定义过滤器:http://jinja.pocoo.org/docs/dev/api/#writing-filters

    它非常简单实用 . 在myTemplate.txt文件中,我写道:

    {{ data|pythonFct }}
    

    并在python脚本中:

    import jinja2
    
    def pythonFct(data):
        return "This is my data: {0}".format(data)
    
    input="my custom filter works!"
    
    loader = jinja2.FileSystemLoader(path or './')
    env = jinja2.Environment(loader=loader)
    env.filters['pythonFct'] = pythonFct
    result = env.get_template("myTemplate.txt").render(data=input)
    print(result)
    
  • 0

    如果你正在使用Django,你可以通过上下文传递函数:

    context = {
        'title':'My title',
        'str': str,
    }
    ...
    return render(request, 'index.html', context)
    

    现在,您将能够在jinja2模板中使用 str 函数

  • 3

    有没有办法导入一整套python函数,并可以从jinja2访问它们?

    是的,除了上面的其他答案,这对我有用 .

    创建一个类并使用相关方法填充它,例如

    class Test_jinja_object:
    
        def __init__(self):
            self.myvar = 'sample_var'
    
        def clever_function (self):
            return 'hello'
    

    然后在视图函数中创建类的实例,并将结果对象作为render_template函数的参数传递给模板

    my_obj = Test_jinja_object()
    

    现在在您的模板中,您可以像这样调用jinja中的类方法

    {{ my_obj.clever_function () }}
    
  • 8

    要导入所有内置函数,您可以使用:

    app.jinja_env.globals.update(__builtins__)
    

    如果这不起作用,请在 __builtins__ 之后添加 .__dict__ .

    基于John32323's answer .

相关问题