可以访问Contex的Jinja扩展

2024-05-19 01:13:35 发布

您现在位置:Python中文网/ 问答频道 /正文

是否有可能在呈现模板的同时写入扩展名Jinja2?我想写一个扩展来访问一个上下文变量并基于这个变量输出一些数据。关于如何编写这样一个扩展名,我找不到足够的信息。在

现在,我有这个:

class CsrfExtension(jinja2.ext.Extension):
    r""" Adds a {% csrf %} tag to Jinja. """

    tags = set(['csrf'])
    template = '<input type="hidden" name="csrfmiddlewaretoken" value="%s">'

    def parse(self, parser):
        token = next(parser.stream)
        lineno = token.lineno
        return self.call_method('_render_csrf', lineno=lineno)

    def _render_csrf(self, value, name, *args, **kwargs):
        csrf_token = somehow_get_variable('csrf_token')
        return jinja2.Markup(self.template % csrf_token)

但是,在foo.jinja

^{pr2}$

我明白了

SyntaxError at /
invalid syntax (foo.jinja, line 7)

我想我会得到一个名称错误,因为somehow_get_variable()没有定义。我需要知道a)如何从当前上下文中获取变量,以及b)如何正确地编写扩展。在

还有,为什么选7号线?{% csrf %}标记在第5行。即使我将foo.jinja修改为只有一行中有{% csrf %}标记,它还是显示第7行。在


Tags: nameselftokenparserjinja2returnfoovalue
2条回答

找到了。似乎Jinja从Jinja AST(?)生成Python代码而这种转换失败了,因此导致了语法错误。jinja2.nodes.ContextReference()可用于获取呈现上下文。在

class CsrfExtension(jinja2.ext.Extension):
    r""" Adds a {% csrf %} tag to Jinja. """

    tags = set(['csrf', 'csrf_token'])
    template = u'<input type="hidden" name="csrfmiddlewaretoken" value="%s">'

    def parse(self, parser):
        lineno = next(parser.stream).lineno
        ctx_ref = jinja2.nodes.ContextReference()
        node = self.call_method('_render_csrf', [ctx_ref], lineno=lineno)
        return jinja2.nodes.CallBlock(node, [], [], [], lineno=lineno)

    def _render_csrf(self, context, caller):
        csrf_token = context['csrf_token']
        return jinja2.Markup(self.template % unicode(csrf_token))

csrf = CsrfExtension

我刚刚遇到了这个问题,我发现解决方案是用@contextfunction修饰符装饰call方法。它告诉运行时将活动上下文作为第一个参数传递给call方法。在

from jinja2 import nodes
from jinja2.ext import Extension
from jinja2.utils import contextfunction


class MyExtension(Extension):
    """See http://jinja.pocoo.org/docs/2.10/extensions/#module-jinja2.ext
    for more information on how to create custom Jinja extensions.
    """
    tags = set(['myext'])

    def __init__(self, environment):
        super(MyExtension, self).__init__(environment)

    def parse(self, parser):
        lineno = next(parser.stream).lineno

        # Parse args if you need them ...
        # args = [parser.parse_expression()]

        node = nodes.CallBlock(self.call_method('_myext_method', args),
                               [], [], []).set_lineno(lineno)
        return parser.parse_import_context(node, True)

    @contextfunction
    def _myext_method(self, context, args, caller):
        # Return what you need
        return "Hello I am a custom extension, rendered with: %r" % context

相关问题 更多 >

    热门问题