【问题标题】:How to write a "joiner" extension for Jinja2?如何为 Jinja2 编写“joiner”扩展?
【发布时间】:2010-10-01 05:33:24
【问题描述】:

您好,我一直在尝试为 jinja2 创建一个扩展,该扩展将使用分隔符连接多个项目,同时跳过评估为空白的项目(模板片段)。

其中有几个片段,你永远不知道哪些片段是非空的,哪些片段是非空的。

听起来像是一项微不足道的任务,但我很难让它在 jinja2 中工作。也许部分原因是 jinja 不允许定义自定义模板节点。

您有什么建议吗?下面是一个将完成解析工作的 sn-p,但它缺少评估部分。

class JoinerExtension(Extension):
    """Template tag that joins non-whitespace (string) items
    with a specified separator

    Usage syntax:

    {% joinitems separator='|' %}
    ....
    {% separator %}
    ....
    {% separator %}
    ....
    {% endjoinitems %}

    where value of "separator" within the joinitems tag
    can be an expression, not necessarily a sting
    """

    tags = set(['joinitems'])

    def parse(self, parser):
        """parse function for the 
        joinitems template tag
        """
        lineno = next(parser.stream).lineno

        #1) read separator
        separator = None
        while parser.stream.current.type != 'block_end':
            name = parser.stream.expect('name')
            if name.value != 'separator':
                parser.fail('found %r, "separator" expected' %
                            name.value, name.lineno,
                            exc=TemplateAssertionError)

            # expressions
            if parser.stream.current.type == 'assign':
                next(parser.stream)
                separator = parser.parse_expression()
            else:
                var = parser.stream.current
                parser.fail('assignment expected after the separator' %
                            var.value, var.lineno,
                            exc=TemplateAssertionError)

        #2) read the items
        items = list()
        end_tags = ['name:separator', 'name:endjoinitems']
        while True:
            item = parser.parse_statements(end_tags)
            items.append(item)
            if parser.stream.current.test('name:separator'):
                next(parser.stream)
            else:
                next(parser.stream)
                break

【问题讨论】:

    标签: python templates jinja2


    【解决方案1】:

    内置的joiner 类可能会起作用吗?这是文档中的一个简单示例。

    {% set pipe = joiner("|") %}
    {% if categories %} {{ pipe() }}
        Categories: {{ categories|join(", ") }}
    {% endif %}
    {% if author %} {{ pipe() }}
        Author: {{ author() }}
    {% endif %}
    {% if can_edit %} {{ pipe() }}
        <a href="?action=edit">Edit</a>
    {% endif %}
    

    您提到提前不知道哪些片段将是空的;也许可以在“显示”之前将每个片段的值存储在变量中,以便您可以确定哪些片段确实是空的。例如:

    {% set pipe = joiner("|") %}
    {% set fragment = gen_fragment1() %}
    {% if fragment|trim is not "" %} 
        {{ pipe() }} {{ fragment }}
    {% endif %}
    ...
    

    您甚至可以将上述模式封装在一个宏中以减少重复:

    {% set pipe = joiner("|") %}
    {{ print_if_notblank(pipe, gen_fragment1()) }}
    {{ print_if_notblank(pipe, gen_fragment2()) }}
    ...
    

    其中print_if_notblank 是一个宏定义为:

    {% macro print_if_notblank(separator, content) %}
        {% if content|trim is not "" %}
            {{ separator() }} {{ content }}
        {% endif %}
    {% endmacro %}
    

    【讨论】:

    • 这将起作用,现在使用内置的策略性地放置 {{pipe()}} 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    相关资源
    最近更新 更多