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

iris.Django
Djangoiris.Django
iris.Django
iris.Django
include

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

{% include "partial/header.html" %}
{% include "partial/footer.html" %}
{% include "模板文件" %}
if_exists
{% include "partial/header.html" if_exists %}

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

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

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

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.Djangomacro
定义一个宏函数
{% 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 %}
,

保存宏函数到 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/bootstrap@3.3.7/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中去,让它成为母版的一部分。

变量的输出

.
<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_if_none
{{ userName|default_if_none:"大侠匿名"}}
{{ ""|default_if_none:"n/a" }}
{{ nil|default_if_none:"n/a" }}
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}}
truncatecharstruncatewords
truncatechars_htmltruncatewords_htmltruncatecharstruncatewords
{{ "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+
{{ 5|add:6 }}
{{ 5|add:nothing }}
{{ 5|add:"test" }}
{{ "hello "|add:"john doe" }}
addslashes
{{ "plain' text"|addslashes }}
{{ "plain' text"|addslashes|safe }}
title
{{ "hello there!"|title }}
{{ "HELLO THERE!"|title }}
{{ "HELLO tHERE!"|title }}
yesno,
{{ article.Status|yesno}}
{{ article.Status|yesno:"validated,not validated,unknown validation status"}}
striptags
{{"<title>Hello World</title>"|striptags}}
{{"<title>Hello World</title>"|striptags|safe}}
removetags
{{ "<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
{{ "/?category_id=1"|urlencode }}
linebreaksbrlinebreaks
nl2br
{{ article.Description|linebreaksbr }}
{{ article.Description|linebreaks }}
{{ article.Description|linebreaksbr|safe }}
{{ article.Description|linebreaks|safe }}
length_is
{{ "hello"|length_is:5 }}
integerfloat
{{ "foobar"|integer }}
{{ "5.4"|float|integer }}
{{ "foobar"|float }}
{{ "5.5"|float }}
{{ "5.6"|integer|float }}
floatformat
{{ 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:", "}}
splitjoin
{{ "Hello, 99, 3.140000, good"|split:", "|join:", " }}
stringformatfmt.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 }}
ljustrjustcenterljustrjust
'{{ "test"|ljust:"20" }}'
{{ "test"|ljust:"20"|length }}
'{{ "test"|rjust:"20" }}'
{{ "test"|rjust:"20"|length }}
wordcount
{{ ""|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
<p>{{ ""|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 demo@example.com or visit mit on:</p>
<p>- lorem ipsum http://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum  lorem ipsum</p>
<p>- lorem ipsum  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>
urlizetruncurlize...
<p>{% filter urlizetrunc:15|safe %}</p>
<p>Please mail me at demo@example.com or visit mit on:</p>
<p>- lorem ipsum http://www.kandaoni.com lorem ipsum</p>
<p>- lorem ipsum  lorem ipsum</p>
<p>- lorem ipsum  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
safeautoescape
用safe关闭自动转义
{{ "<script>alert('xss');</script>"|safe}}
强制开启自动转义
{% autoescape on %}
{{ "<script>alert('xss');</script>" }}
{% endautoescape %}
强制关闭自动转义,相当于使用了safe
{% autoescape off %}
{{ "<script>alert('xss');</script>" }}
{% endautoescape %}
escapeautoescape off
{{ "<script>alert('xss');</script>" }}
相当于
{% autoescape off %}
{{ "<script>alert('xss');</script>"|escape }}
{% endautoescape %}
{% 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
for
{% for item in articles %}
<li class="item">
    <a href="/article/{{item.Id}}" class="link">
        <h5 class="title">{{item.Title}}</h5>
    </a>
</li>
{% endfor %}
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 %}
forreversedsorted
{% 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 %}
forempty
{% 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 %}
cyclecycle
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 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结构体内置方法

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.Djangowithwith
{% with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %} %}标题:{{title}},关键词:{{keywords}}。{% endwith %}
{% include "partial/header.html" with title="这是声明给header使用的title" keywords="这是声明给header使用的keywords" %}
withendwith
iris.Djangoset
{% 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 "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)

我们先在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模板中输出:

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

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