前面的章节中,我们选择了使用iris.Django
作为我们前端使用的模板引擎,因此我们这里只介绍它的相关语法。
iris.Django
模板语法和使用
iris.Django
模板引擎的模板解析器是pongo2,它是一个类似于 Django 模板语法的模板引擎。Django 是一个开放源代码Python编写的Web应用框架。它的模板引擎语法相对简单,清晰,使用起来也非常方便。因此我们就使用它做为我们的博客的前端模板引擎了。
模板的嵌套引用
往往制作模板的时候,我们会将一些公共部分,比如header、footer、aside等部分,抽离出来独立存放,不需要在每一个页面都重复编写,只需要在每一个页面引入它们即可。这个时候,我们可以使用include标签。
{% include "partial/header.html" %}
{% include "partial/footer.html" %}
include可以将一个拆分出来的代码片段(fragment)嵌入到完整的文档中。使用形式是{% include "模板文件" %}
。
模板的继承
模板的继承有点像ppt中的母版一样,我们定义好一个骨架,将一个页面都写好,大部分不用变动,需要变动的部分使用block标签包裹起来:
{% block title %}
<title>basetitle>
{% endblock %}
这样定义的好处是,可以在继承它的模板中,重写这个block,不重写就按母版来显示。 比如我们定义了一个base.html
html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block title %}
<title>basetitle>
{% endblock %}
<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>contenth4>
{% endblock %}
div>
div>
div>
body>
html>
然后在index.html中继承这个base.html
{% extends 'base.html' %}
{% block title %}
<title>indextitle>
{% endblock %}
{% block content %}
<div class="col-md-9">
<h3>indexh3>
<p>index contentp>
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:"大侠匿名"}}
使用length
输出长度:
{{ value|length }}
如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。
date
可以格式化时间:
{{ value|date:``"2006-01-02 15:04"}}
注意,这个value必须是time.Time类型,不是时间戳,如果是时间戳它会报错的。时间戳要么在控制器将它转成time.Time类型,要么就使用我们自定义的模板函数:
{{stampToDate(nowStamp, "2006-01-02 15:04")}}
truncatechars
字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾:
{{ value|truncatechars:9}}
{{ value|truncatewords:9}}
截断除了字符串截断truncatechars
,还支持按单词截断truncatewords
upper
、lower
可以对单字进行大小写转换:
{{ value|upper}}
{{ value|lower}}
safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,这样是为了安全,防止xss攻击。如果不想用转义,就使用safe
{{ article.Content|safe}}
后端传递变量到模板
实际网站开发中,我们在控制器中的变量,需要使用特定的函数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: "内容在此",
},
}
ctx.ViewData("article", article)
ctx.View("index.html")
}
然后在index.html模板中输出:
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Worldtitle>
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一份来在上面做修改。