Jinja 模板的 % spaceless % 标签?

Posted

技术标签:

【中文标题】Jinja 模板的 % spaceless % 标签?【英文标题】:% spaceless % tag for Jinja templates?Jinja 模板的 % spaceless % 标签? 【发布时间】:2011-07-08 15:34:18 【问题描述】:

Django 有一个有用的% spaceless % 标签,可以从 html 中去除多余的空格。

我的模板产生了很多空白,在任何地方添加%--% 来进行空白控制实在是太痛苦了。有没有人看到类似 % spaceless % 的 Jinja 过滤器,或者可能是 % htmltidy %,这样我可以在开发时查看干净的 HTML?

【问题讨论】:

值得一提:没有一个答案适用于 jinja 块(在任何由 spaceless/filter 等包裹的块内做 spaceless) 【参考方案1】:

有一个 jinja2 扩展可以实现这个效果,由 jinja2 开发者编写

https://github.com/mitsuhiko/jinja2-htmlcompress

【讨论】:

使用扩展后:去除html标签之间的空白,也去除jinja标签之间的空白,必须使用  ' ' 来解决 我最近重新审视了这个问题。 @joel-santirso 更好地回答了这个问题。 遗憾的是它不支持 Python 3。【参考方案2】:

当我想打印行内块级元素而不将它们分开(例如渲染块的流体网格)时遇到了这个问题,但我想要一个看起来干净的标记。

jinja2-htmlcompress 去除 HTML 标签之间的空格,也去除 jinja 标签和变量之间的空格。这并不理想,因为它会迫使您使用诸如 ' ' 之类的变通方法或诸如  之类的硬编码html 实体。

coffin 的 spaceless 标签看起来是理想的解决方案,但它添加了依赖项 (django) 和许多不必要的功能。

如果你只想使用 Django 的 spaceless 标签,可以使用我从 coffin 改编的以下代码:

jinja_extensions.py

# -*- coding: utf-8 -*-

from jinja2 import nodes
from jinja2.ext import Extension

import re


class SpacelessExtension(Extension):
    """
    Removes whitespace between HTML tags at compile time, including tab and newline characters.
    It does not remove whitespace between jinja2 tags or variables. Neither does it remove whitespace between tags
    and their text content.
    Adapted from coffin:
        https://github.com/coffin/coffin/blob/master/coffin/template/defaulttags.py
    """

    tags = set(['spaceless'])

    def parse(self, parser):
        lineno = parser.stream.next().lineno
        body = parser.parse_statements(['name:endspaceless'], drop_needle=True)
        return nodes.CallBlock(
            self.call_method('_strip_spaces', [], [], None, None),
            [], [], body,
        ).set_lineno(lineno)

    def _strip_spaces(self, caller=None):
        return re.sub(r'>\s+<', '><', caller().strip())

无论您在哪里定义 jinja2 环境

extensions=['path.to.jinja_extensions.SpacelessExtension']

使用示例

<style>
    *, *:before, *:after  -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; 
    .features 
        text-align: center;
    
        .features div 
            display: inline-block;
            text-align: left;
            width: 25%;
            padding: 20px;
        
        /* A style to help us identify the blocks */
        .features div:nth-child(odd) 
            background: #f5f5f5;
        
    @media only screen and (max-width: 319px) 
        /* For small screens, display a single feature per line */
        .features div 
            width: 100%;
        
    
</style>
% spaceless % # We remove whitespace between these inline-block tags without affecting the markup #
<div class="features">
    <div>
        <h2>Feature 1</h2>
        <p>Content</p>
    </div>
    <div>
        <h2>Feature 2</h2>
        <p>Content</p>
    </div>
    <div>
        <h2>Feature 3</h2>
        <p>Content</p>
    </div>
    <div>
        <h2>Feature 4</h2>
        <p>Content</p>
    </div>
    <div>
        <h2>Feature 5</h2>
        <p>Content, second line on desktop</p>
    </div>
</div>
% endspaceless %

无空格的结果

没有空格的结果 (注意不可见的空格已经把第四块移到了下一行)

【讨论】:

它将转义 html 字符,例如 > 替换为 > 这很棒。但在 Python 3 中,next 需要替换为 __next__ @tremby 最初的项目有一些优秀的 PR,似乎一直在徘徊。我有一个fork,在那里我进行了一系列改进,包括 py3 兼容性。 如果您使用自动转义,请在最后一行使用return Markup(re.sub(r'&gt;\s+&lt;', '&gt;&lt;', caller().unescape().strip())),而不是丢弃所有标签。【参考方案3】:

% filter trim % 等价于% spaceless %

【讨论】:

trim 过滤器是否也会删除标签之间的空格? 不,这不会删除标签之间的空格。 jinja.pocoo.org/docs/2.9/templates/#id11jinja.pocoo.org/docs/2.9/templates/#trim【参考方案4】:
% filter replace("\t", " ")|replace("    ", " ")|replace("   ", " ")|replace("  ", " ")|replace("\n ", "\n")|replace("\n\n", "\n") %

我用它来用一个分隔符替换多个空格。 如果没有扩展,效果不好但高效。

【讨论】:

一个简单的% filter replace('\n', '') % stuff on many lines % endfilter %'\n' 也是一种只写一行的好方法。例如在% for % 块中【参考方案5】:

我在做:

% filter trim %
... code ...
% endfilter %

【讨论】:

以上是关于Jinja 模板的 % spaceless % 标签?的主要内容,如果未能解决你的问题,请参考以下文章

030:spaceless和autoescape 标签

Jinja2模板语言

Flask Jinja2模板语言

Jinja 找不到模板路径

Ansible Jinja2 模板概述 --01

Jinja2 模板使用 Django 模板标签