7

iris.Django模板引擎的语法格式和语法标签使用方法,include标签传递变量方法

 3 years ago
source link: https://studygolang.com/articles/32489
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

基础配置篇:博客模板的格式语法和后端如何传递数据到模板逻辑

前面的章节中,我们选择了使用 iris.Django 作为我们前端使用的模板引擎,因此我们这里只介绍它的相关语法。

在网络上,关于 Django 模板的标签和语法教程少之又少,并且很多都是不全面的,要么就是抄来抄去的无用文章,要么就是简单寥寥几个标签,很多时候,都不能满足使用。比如include引入模板后,如何传递变量、如何在页面声明一个临时变量等问题。为了解决网络上缺少介绍内容的问题,我特意翻读了 iris.Django 的源码,并将大部分常用到的标签,都整理出来,供参考和使用。

iris.Django 模板语法和使用

iris.Django 模板引擎的模板解析器是pongo2,它是一个类似于 Django 模板语法的模板引擎。Django 是一个开放源代码Python编写的Web应用框架。它的模板引擎语法相对简单,清晰,使用起来也非常方便。因此我们就使用它做为我们的博客的前端模板引擎了。

模板的嵌套引用 include

往往制作模板的时候,我们会将一些公共部分,比如header、footer、aside等部分,抽离出来独立存放,不需要在每一个页面都重复编写,只需要在每一个页面引入它们即可。这个时候,我们可以使用include标签。

{% include "partial/header.html" %}
{% include "partial/footer.html" %}

include可以将一个拆分出来的代码片段(fragment)嵌入到完整的文档中。使用形式是 {% include "模板文件" %}

如果需要引入的模板不存在的话,它会报错,如我我们不知道引入的模板是否存在,则需要增加 if_exists 判断。

{% include "partial/header.html" if_exists %}

这样如果header.html模板存在的话,则会引入,即使不存在,也不会报错,只是被忽略掉了。

默认情况下,include引入的模板,它会继承当前模板的所有变量,如果想给include引入的模板增加另外的变量,可以使用 with 来增加。如:

{% include "partial/header.html" with title="这是声明给header使用的title" %}

这样就给include引入的模板定义了title变量,当前模板的其他变量它同样也可以继续使用了。

如果需要声明多个变量给include引入的模板使用,可以连续使用 key=value 的形式增加,它们之间使用空格隔开,如:

{% include "partial/header.html" with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %}

如果只想让include引入的模板使用指定的几个变量,而不是当前模板的所有变量,可以使用only来做限制:

{% include "partial/header.html" with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" only %}

然后在header.html中使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
    <meta name="keywords" content="{{keywords}}">
</head>

模板代码片段宏函数 macro

iris.Django 模板引擎可以很简便的定义一些宏函数代码片段。宏代码片段相当于一个函数,它只能调用从参数传入的变量。类似于使用include。不过macro有限定的作用域。如文章我们给文章列表的文章item使用 macro

定义一个宏函数
{% macro article_detail(article) %}
<li class="item">
    <a href="/article/{{article.Id}}" class="link">
        <h5 class="title">{{article.Title}}</h5>
    </a>
</li>
{% endmacro %}
使用定义的宏函数
{% for item in articles %}
    {{ article_detail(item) }}
{% endfor %}

同时宏函数还可以保存到独立的文件中,然后通过import来嵌套进来。当一个文件中包含多个宏函数,可以使用 , 将隔开连续引入多个宏函数。还可以使用as来设置别名:

保存宏函数到 article.helper

{% macro article_detail(article) %}
<li class="item">
    <a href="/article/{{article.Id}}" class="link">
        <h5 class="title">{{article.Title}}</h5>
    </a>
</li>
{% endmacro %}
{% macro article_detail2(article) %}
<li class="item">
    <a href="/article/{{article.Id}}" class="link">
        <h5 class="title">{{article.Title}}</h5>
    </a>
</li>
{% endmacro %}

在index.html中引入:

用import引入:
{% import "article.helper" article_detail, article_detail2 as article_detail_new, article_detail as new_item %}
调用:
{% for item in articles %}
    {{ article_detail(item) }}
    {{ article_detail_new(item) }}
    {{ new_item(item) }}
{% endfor %}

模板的继承 extends

模板的继承有点像ppt中的母版一样,我们定义好一个骨架,将一个页面都写好,大部分不用变动,需要变动的部分使用block标签包裹起来:

{% block title %}
    <title>base</title>  <!-- 如果扩写了就是扩写的,不扩写就还是用base -->
{% endblock %}

这样定义的好处是,可以在继承它的模板中,重写这个block,不重写就按母版来显示。

比如我们定义了一个base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% block title %}
        <title>base</title>  <!-- 如果扩写了就是扩写的,不扩写就还是用base -->
    {% endblock %}
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .header {
            width: 100%;
            height: 50px;
            background-color: #369;
        }
    </style>
</head>
<body>

<div class="header"></div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            {% include 'aside.html' %}
        </div>
        <div class="col-md-9">
            {% block content %}
                <h4>content</h4>
            {% endblock %}
        </div>
    </div>
</div>
</body>
</html>

然后在index.html中继承这个base.html

{% extends 'base.html' %}

{% block title %}
    <title>index</title>
{% endblock %}


{% block content %}
    <div class="col-md-9">
        <h3>index</h3>
        <p>index content</p>
    </div>

{% endblock %}

这样就是使用base.html作为母版,并在index.html 中重写了title、content两个部分。

注意:如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。

在使用继承的情况下,尽可能将可能会变动的数据,都包裹在block中,因为block即使在后续的页面不重写,也不影响模板的解析,而需要重写的时候就更方便。

同样地,如果后续写到某一块,发现多个页面都需要使用到,那么这时候,就把添加到base.html中去,让它成为母版的一部分。

变量的输出

Django 模板中遍历复杂数据结构的关键是句点字符 . ,变量输出边界定义是双大括号。有一个对象是people,它有Name、Gender、Level属性,在模板中输出就是:

<ul>
  <li>网站:{{siteName}}</li>
  <li>名字:{{people.Name}}</li>
  <li>性别:{{people.Gender}}</li>
  <li>等级:{{people.Level}}</li>
</ul>

变量的过滤

同时,输出变量的时候,还支持使用过滤器,来对数据进行初级过滤,格式是:

{{obj|filter__name:param}}

比如一个变量,当它有值的时候,就输出当前值,没有值的时候,就输出默认值:

使用 default 设置默认值:

{{ userName|default:"大侠匿名"}}

default只要是空都会认为没有。我们还可以使用 default_if_none 来进行处理

{{ userName|default_if_none:"大侠匿名"}}
{{ ""|default_if_none:"n/a" }}
{{ nil|default_if_none:"n/a" }}

get_digit 可以获取变量中的数字,指定get_digit的值的话,可以获取倒数第几个数字。如:

{{ 1234567890|get_digit:0 }}
{{ 1234567890|get_digit }}
{{ 1234567890|get_digit:2 }}
{{ 1234567890|get_digit:"4" }}
{{ 1234567890|get_digit:10 }}
{{ 1234567890|get_digit:15 }}

使用 length 输出长度:

{{ value|length }}

如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。

divisibleby 可以判断一个变量是否可以被整除,如:

{{ 21|divisibleby:3 }}
{{ 21|divisibleby:"3" }}
{{ 21|float|divisibleby:"3" }}
{{ 22|divisibleby:"3" }}
{{ 85|divisibleby:simple.number }}
{{ 84|divisibleby:simple.number }}

date 可以格式化时间:

{{ value|date:``"2006-01-02 15:04"}}

注意,这个value必须是time.Time类型,不是时间戳,如果是时间戳它会报错的。时间戳要么在控制器将它转成time.Time类型,要么就使用我们自定义的模板函数:

{{stampToDate(nowStamp, "2006-01-02 15:04")}}

truncatecharstruncatewords 字符串字符、单词多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾:

{{ value|truncatechars:9}}
{{ value|truncatewords:9}}

截断除了字符串截断 truncatechars ,还支持按单词截断 truncatewords

truncatechars_htmltruncatewords_html 功能类似 truncatecharstruncatewords 。但是这这2个标签用来处理截取html中的字符串,它不会破坏html结构。一个是按字符截取,一个是按单词截取。截断的字符串将以可翻译的省略号序列(“...”)结尾:

{{ "This is a long test which will be cutted after some chars."|truncatechars_html:25 }}
{{ "This is a long test which will be cutted after some words."|truncatewords_html:5|safe }}

upperlower 可以对单字进行大小写转换:

{{ value|upper}}
{{ value|lower}}

capfirst 可以实现句子首字母大写效果,如:

{{ "hello there!"|capfirst }}

cut 可实现删除变量中特定的字符。如:

{{ 15|cut:"5" }}
{{ "Hello world"|cut: " " }}

add 可以对要输出的内容进行追加。相当于golang中的 + ,数字则会相加后输出结果,字符串则会拼接在一起。如:

{{ 5|add:6 }}
{{ 5|add:nothing }}
{{ 5|add:"test" }}
{{ "hello "|add:"john doe" }}

addslashes 则会在指定的预定义字符前添加反斜杠。这些字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL字符)。如:

{{ "plain' text"|addslashes }}
{{ "plain' text"|addslashes|safe }}

title 标签可以实现句子中每一个单词的首字母都变成大写,并将其余部分变成小写,用于格式化标题的输出。如:

{{ "hello there!"|title }}
{{ "HELLO THERE!"|title }}
{{ "HELLO tHERE!"|title }}

yesno yesno用于验证一个变量是否有效,它可以定义三种结果,三种结果分别用英文逗号 , 隔开,有效值、无效值、不知道类型。如果不定义,也可以留空。如:

{{ article.Status|yesno}}
{{ article.Status|yesno:"validated,not validated,unknown validation status"}}

striptags striptags 类似PHP的strip_tags函数,可以剥去字符串中的 HTML、XML 以及 PHP 的标签。该标签始终会剥离 HTML 注释。如:

{{"<title>Hello World</title>"|striptags}}
{{"<title>Hello World</title>"|striptags|safe}}

removetags 标签可以删除指定的html标签。如:

{{ "<strong><i>Hello!</i></strong>"|removetags:"i"|safe }}

pluralize 标签可以判断一个变量是否是复数。如:

customer{{ 0|pluralize }}
customer{{ 1|pluralize }}
customer{{ 2|pluralize }}
cherr{{ 0|pluralize:"y,ies" }}
cherr{{ 1|pluralize:"y,ies" }}
cherr{{ 2|pluralize:"y,ies" }}
walrus{{ 0|pluralize:"es" }}
walrus{{ 1|pluralize:"es" }}
walrus{{ simple.number|pluralize:"es" }}

random 可以随机输出集合中的一个值。如:

<p>{{ intList|random }}</p>

firstlast 可以用于输出变量中的最开始一个字符和最后一个字符。如:

{{ "Test"|first }}
{{ "Test"|last }}

urlencode urlencode标签可以对变量进行url百分号编码。如:

{{ "https://www.kandaoni.com/?category_id=1"|urlencode }}

linebreaksbrlinebreaks 两个标签都可以将变量的值中的换行符变成 <br/> ,相当于PHP的 nl2br 函数。如:

{{ article.Description|linebreaksbr }}
{{ article.Description|linebreaks }}
{{ article.Description|linebreaksbr|safe }}
{{ article.Description|linebreaks|safe }}

length_is length_is可以判断变量的值的长度。只能判断字符串,数字是不行的。如:

{{ "hello"|length_is:5 }}

integerfloat 标签可以将变量的值转换成整数、浮点数。如:

{{ "foobar"|integer }}
{{ "5.4"|float|integer }}
{{ "foobar"|float }}
{{ "5.5"|float }}
{{ "5.6"|integer|float }}

floatformat 标签可以将变量的值按浮点数格式保留指定小数点,默认只保留以为,如果末位是0,则不保留小数点。如果指定小数点后位数,则按指定位数显示。如:

{{ 34.23234|floatformat }}
{{ 34.00000|floatformat }}
{{ 34.23234|floatformat:3 }}
{{ 34.00000|floatformat:3 }}
{{ "34.23234"|floatformat }}
{{ "34.00000"|floatformat }}
{{ "34.23234"|floatformat:3 }}
{{ "34.00000"|floatformat:3 }}

join 可以将一个数组按给定的分隔符合并在一起成为字符串。如:

{{intList|join:", "}}

split 刚好和 join 相反,它可以将一个字符串按给定的分隔符将一个字符串转换成数组。如:

{{ "Hello, 99, 3.140000, good"|split:", "|join:", " }}

stringformat 可以将数字、字符串格式化成指定的格式输出。相当于 fmt.Sprintf() 。如:

{{ 0.55555|stringformat:"%.2f" }}
{{ 888|stringformat:"Test: %d" }}
{{ "你好"|stringformat:"Chinese: %s" }}

make_list 可以将字符串按字符拆分成数组,相当于 []rune("你好啊") 。如:

{{ "你好啊"|make_list|join:", " }}
{% for char in "你好啊"|make_list %}{{ char }},{% endfor %}

center 这个标签比较有意思,可以将字符串格式化成指定长度,并将字符串放在中间,旁边使用空格填充。如果给定的长度小于字符串长度,则不会做改变。如:

'{{ "test"|center:3 }}'
'{{ "test"|center:20 }}'
{{ "test"|center:20|length }}

ljustrjust 这两个标签和 center 差不多,都是给字符串填充到指定长度,但是填充方向不同。 ljust 会在右边填充空格,即让字符串靠左。 rjust 会在左边填充空格,即让字符串靠右。如:

'{{ "test"|ljust:"20" }}'
{{ "test"|ljust:"20"|length }}
'{{ "test"|rjust:"20" }}'
{{ "test"|rjust:"20"|length }}

wordcount 用来统计字符串的长度。它有2种使用方式,一种是在字符串后面,另一种是使用 filter 标签。如:

{{ ""|wordcount }}
{% filter wordcount %}{% lorem 25 w %}{% endfilter %}

wordwrap 可以将字符串按给定的长度换行。如:

{{ "hello world"|wordwrap:2 }}
<pre>{% filter wordwrap:5 %}{% lorem 26 w %}{% endfilter %}</pre>
{{ "Lorem ipsum dolor sit amet, consectetur adipisici elit."|wordwrap:2|linebreaksbr|safe }}

urlize 会自动给url、邮箱添加上a标签,并自动增加nofollow的rel。这个用来处理文章正文比较合适。urlize还支持设置true和false,用来说明显示的连接内容是否转义。如:

<p>{{ "https://www.kandaoni.com"|urlize|safe }}</p>
<p>{{ "www.kandaoni.com"|urlize|safe }}</p>
<p>{{ "kandaoni.com"|urlize|safe }}</p>
<p>{% filter urlize:true|safe %}</p>
<p>Please mail me at [email protected] or visit mit on:</p>
<p>- lorem ipsum http://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum https://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum https://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum www.kandaoni.com/test="test" lorem ipsum</p>
<p>{% endfilter %}</p>
<p>{% filter urlize:false|safe %}</p>
<p>- lorem ipsum www.kandaoni.com/test="test" lorem ipsum</p>
<p>{% endfilter %}</p>

urlizetrunc 的作用和 urlize 差不多,都是自动给url、邮箱添加上a标签,但是可以设置截取显示部分url内容,超过指定长度部分使用 ... 代替。如:

<p>{% filter urlizetrunc:15|safe %}</p>
<p>Please mail me at [email protected] or visit mit on:</p>
<p>- lorem ipsum http://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum https://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum https://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum www.kandaoni.com/test="test" lorem ipsum</p>
<p>{% endfilter %}</p>

escapejs 会将字符串按 \uxxxx 编码预设的部分字符。如:

{{ "<p>aaa</p><script>alert('xss');</script><p>bbbb</p>"|escapejs|safe }}

slice 可以对字符串、数组进行截取指定长度的数据。如:

{{ "Test"|slice:"1:" }}
{{ "Test"|slice:":3" }}
{{ "Test"|slice:"1:3"|join:"," }}
{{ intList|slice:"1:5"|join:"," }}

safe Django的模板中会对HTML标签和JS等语法标签进行自动转义,这样是为了安全,防止xss攻击。

如果不想用转义,就使用 safe 来声明要输出的内容是安全的,它就不会自动转义,也可以使用 autoescape 标签来控制开启和关闭自动转义:

用safe关闭自动转义
{{ "<script>alert('xss');</script>"|safe}}
强制开启自动转义
{% autoescape on %}
{{ "<script>alert('xss');</script>" }}
{% endautoescape %}
强制关闭自动转义,相当于使用了safe
{% autoescape off %}
{{ "<script>alert('xss');</script>" }}
{% endautoescape %}

escape escape 还可以进行声明转义。由于默认已经会自动转义,因此在此使用escape的话,会形成转义2次。因此使用 autoescape off 关闭转义后,再使用escape就等于直接输出。如:

{{ "<script>alert('xss');</script>" }}
相当于
{% autoescape off %}
{{ "<script>alert('xss');</script>"|escape }}
{% endautoescape %}

上面所有的filter 标签,都可以使用 {% filter 标签名 %}内容{% endfilter %} 来使用。比如:

{% filter lower %}This is a nice test; let's see whether it works. Foobar. {{ simple.xss }}{% endfilter %}

{% filter truncatechars:10|lower|length %}This is a nice test; let's see whether it works. Foobar. {{ simple.number }}{% endfilter %}

<p>{% filter urlize:false|safe %}</p>
<p>- lorem ipsum www.kandaoni.com/test="test" lorem ipsum</p>
<p>{% endfilter %}</p>

for 遍历数组、slice等对象

for 用于循环访问数组中的每个项目,从而使该项目在上下文变量中可用。 例如,要显示articleList中提供的文章列表:

{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}

还可以输出for循环的计数,以及剩余数量,还可以使用 pluralize 判断数量是否是复数。如:

{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">第{{ forloop.Counter }}篇,剩余{{ forloop.Revcounter}}篇,{{ forloop.Revcounter|pluralize:"多于1篇" }}:{{item.Title}}</h5>
    </a>
</li>
{% endfor %}

for 还可以使用 reversed 翻转数组, sorted 按int排序数组。如:

{% for item in articles reversed %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}
{% for item in articles sorted %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}
{% for item in articles reversed sorted %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}

for 还支持判断是否为空数组或者nil等,使用 empty 来输出不存在的情况。如:

{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% empty %}
<div>没有内容</div>
{% endfor %}

它等价于使用if判断,但是这样写可以更简洁:

{% if articles %}
{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}
{% else %}
<div>没有内容</div>
{% endif %}

cycle 标签。在for循环中,我们还可以使用 cycle 标签,来循环逐个输出定义中的变量。

每次遇到此 cycle 标签时,都会产生其参数之一。 第一个参数在第一次遇到时产生,第二个参数在第二次遇到时产生,依此类推。 一旦所有参数用尽,标记将循环到第一个参数并再次产生它。

此标记在循环中特别有用。如:

{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">Title,Id 逐个出现:{% cycle item.Title item.Id %}</h5>
    </a>
</li>
{% endfor %}

或者使用 as 来定义别名,再通过别名输出:

{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        {% cycle item.Title item.Id as cycleitem %}
        <h5 class="title">Title,Id 逐个出现:{{ cycleitem }}</h5>
    </a>
</li>
{% endfor %}

在模板中使用数学算术计算

整数和复数表达式 integers and complex expressions
{{ 10-100 }}
{{ -(10-100) }}
{{ -(-(10-100)) }}
{{ -1 * (-(-(10-100))) }}
{{ -1 * (-(-(10-100)) ^ 2) ^ 3 + 3 * (5 - 17) + 1 + 2 }}

浮点数 floats
{{ 5.5 }}
{{ 5.172841 }}
{{ 5.5 - 1.5 == 4 }}
{{ 5.5 - 1.5 == 4.0 }}

乘法、除法、整除 mul/div
{{ 2 * 5 }}
{{ 2 * 5.0 }}
{{ 2 * 0 }}
{{ 2.5 * 5.3 }}
{{ 1/2 }}
{{ 1/2.0 }}
{{ 1/0.000001 }}

逻辑表达式 logic expressions
{{ !true }}
{{ !(true || false) }}
{{ true || false }}
{{ true or false }}
{{ false or false }}
{{ false || false }}
{{ true && (true && (true && (true && (1 == 1 || false)))) }}

浮点数比较 float comparison
{{ 5.5 <= 5.5 }}
{{ 5.5 < 5.5 }}
{{ 5.5 > 5.5 }}
{{ 5.5 >= 5.5 }}

取模、取余 remainders
{{ (simple.number+7)%7 }}
{{ (simple.number+7)%7 == 0 }}
{{ (simple.number+7)%6 }}

判断一个变量是否在另一个结果集中 in/not in
{{ 5 in simple.intmap }}
{{ 2 in simple.intmap }}
{{ 7 in simple.intmap }}
{{ !(5 in simple.intmap) }}
{{ not(7 in simple.intmap) }}
{{ 1 in simple.multiple_item_list }}
{{ 4 in simple.multiple_item_list }}
{{ !(4 in simple.multiple_item_list) }}
{{ "Hello" in simple.misc_list }}
{{ "Hello2" in simple.misc_list }}
{{ 99 in simple.misc_list }}
{{ False in simple.misc_list }}

associativity for infix operators
{{ 34/3*3 }}
{{ 10 + 24 / 6 / 2 }}
{{ 6 - 4 - 2 }}

int const与uint比较 uint comparison with int const
{{ simple.uint }}
{{ simple.uint == 8 }}
{{ simple.uint == 9 }}
{{ simple.uint >= 8 }}
{{ simple.uint <= 8 }}
{{ simple.uint < 8 }}
{{ simple.uint > 8 }}

移除模板逻辑标签占用的行

这个需求很多时候会用到,比如在if-elseif 中 或者是for循环中,它会连if-else标签部分的行的空行也输出。如果想清理这一行空行,可以在标签里面的前方或后方使用 - 来实现过滤,如:

{%- if false %}
1st choice
{%- elif false %}
2nd choice
{%- elif true %}
3rd choice
{%- endif %}
正常下
{% for item in articles %}
{{ item.Id }}
{% endfor %}
紧凑:
{% for item in articles %}
{{- item.Id }}
{% endfor %}
不带换行
{% for item in articles -%}
{{ item.Id }}
{%- endfor %}

在模板中使用struct结构体内置方法

比如在article列表中,article的结构体中,定义了内置函数 func (article *Article) GetThumb() ,那么在模板中,是可以直接调用的。如:

{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <img src="{{item.GetThumb()}}" alt="{{item.Title}}" />
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}

模板可以直接使用 {{item.GetThumb()}} 来调用内置的 article.GetThumb() 方法。

在模板中定义变量并赋值

iris.Django 模板引擎的模板解析器提供了可以在模板中声明变量并使用的方法 with 。通过 with 我们可以临时声明单个或多个变量,提供后续使用。多数情况下,我们会将它配合include标签使用。如:

{% with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %} %}标题:{{title}},关键词:{{keywords}}。{% endwith %}
{% include "partial/header.html" with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %}

with 定义的变量需要使用 endwith 来包裹。

另外 iris.Django 还提供 set 的方式来声明变量,这个变量可以在当前模板使用。如:

{% set new_var = "hello" %}{{ new_var }}
{% block content %}{% set new_var = "world" %}{{ new_var }}{% endblock %}
{{ new_var }}{% for item in simple.misc_list %}
{% set new_var = item %}{{ new_var }}{% endfor %}
{{ new_var }}
{% set car=someUndefinedVar %}{{ car.Drive }}No Panic

在模板中输出当前时间

now 标签提供在模板中输出当前时间。now格式化时间的参数遵循golang的时间格式化规则。如果增加fake 参数,则会输出一个特定的加时间代替当前时间。如:

{% now "Mon Jan 2 15:04:05 -0700 MST 2006" fake %}
{% now "2006-01-02 15:04" %}

lorem 随机生成拉丁文样本数据

显示随机的“ lorem ipsum”拉丁文本。 这对于在模板中提供样本数据很有用。也就是占位内容。在开发模板没有真实数据的时候,使用这个标签可以快速填充足够多的随机数据。如:

-----
{% lorem %}
-----
{% lorem 10 %}
-----
{% lorem 3 p %}
-----
{% lorem 100 w %}
-----

模板的注释

iris.Django 的注释我们使用大括号+#来实现注释: {# 注释内容 #}

单行注释使用 {# 这只能注释单行 #} ,多行注释使用 {% comment %}这里注释很多行{% endcomment %}

示例:

空单行注释

{# #}

单行注释

{# testing single line comment #}

用有效标签填充单行注释

{# testing single line comment {% if thing %}{% endif %} #}

用无效标签填充单行注释

{# testing single line comment {% if thing %} #}

用无效语法填充单行注释

{# testing single line comment {% if thing('') %}wow{% endif %} #}

空块注释

{% comment %}{% endcomment %}

填充文本单行块注释

{% comment %}filled block comment {% endcomment %}

空多行块注释

{% comment %}


{% endcomment %}

阻止带有其他标签的注释

{% comment %}
  {{ thing_goes_here }}
  {% if stuff %}do stuff{% endif %}
{% endcomment %}

阻止其中带有无效标签的注释

{% comment %}
  {% if thing %}
{% endcomment %}

使用无效语法阻止注释

{% comment %}
  {% thing('') %}
{% endcomment %}

注释之间的常规标签,以确保其在词法分析器中不会中断

{% if hello %}
{% endif %}
after if
{% comment %}All done{% endcomment %}

后端传递变量到模板

实际网站开发中,我们在控制器中的变量,需要使用特定的函数 ctx.ViewData("article", article) 注入到view中,才能在模板中使用这个变量,比如,我们在IndexPage()控制器中定义一个article,然后将它传递到模板中,用来输出。

我们先在index.go 中的 IndexPage() 函数中添加如下代码

func IndexPage(ctx iris.Context) {
    nowStamp := time.Now().Unix()
    ctx.ViewData("nowStamp", nowStamp)

    article := model.Article{
        Id:          1,
        Title:       "这是一篇文章",
        Keywords:    "这是关键词",
        Description: "这是描述",
        CategoryId:  1,
        Views:       1,
        Category:    model.Category{
            Title: "这是分类名称",
        },
        ArticleData: model.ArticleData{
            ArticleId: 1,
            Content: "<div>内容在此</div>",
        },
    }
    ctx.ViewData("article", article)
    ctx.View("index.html")
}

然后在index.html模板中输出:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
</head>
<body>
Hello World!<br>
{{stampToDate(nowStamp, "2006-01-02 15:04:05")}}<br>
<div>文章标题:{{article.Title}}</div>
<div>文章分类:{{article.Category.Title}}</div>
<div>文章Id:{{article.Id}}</div>
<div>发布时间:{{stampToDate(article.CreatedTime)}}</div>
<div>文章关键词:{{article.Keywords}}</div>
<div>文章描述:{{article.Description}}</div>
<div>文章内容:{{article.ArticleData.Content|safe}}</div>
</body>
</html>

这样,就模板就获得了article变量,然后通过模板语法,将article的成员都输出了。

完整的项目示例代码托管在GitHub上,需要查看完整的项目代码可以到 github.com/fesiong/goblog 上查看,也可以直接fork一份来在上面做修改。

有疑问加站长微信联系(非本文作者)

eUjI7rn.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK