者 | 单雨
责编 | 胡巍巍
出品 | CSDN(ID:CSDNnews)
前言
为了实现模板封装和复用,提高HTML界面调试便捷性以及前后端解耦等目标,Django定义了自己的网络模板语言。
当前介绍模板语言的官方文档已经非常完备,几乎涵盖了开发中需要用到的知识点和需要注意的问题,但同时官方文档也存在一些问题:
翻译不够完善,带来阅读的困难;
一些知识点的介绍过于简短,存在大量的页内链接,阅读时需要跳转到不同的页面,阅读不连贯。
本文基于官方文档系统介绍了Django模板语言的基础知识点,方便快速了解Django模板语言。
模板系统设计哲学
Django的模板系统不是简单的把Python嵌入到HTML中。
它的设计宗旨是:模板系统旨在展示内容, 而不是程序逻辑,因此不在HTML页面中嵌入Python。
简单的说,模板只负责渲染数据,大多数逻辑应该交给视图(view)进行处理。
模板简介
模板是一个简单的文本文件。它可以生成任何基于文本的格式(如 HTML,XML,CSV等)。除了基本的HTML标签外,模板还包含两种额外的元素——变量和标签。
模板中包含的变量可以被替换为变量的值,标签则被替换为相应的模板控制逻辑。示例:
django
{% extends "base_generic.html" %}
{% block title %}{{ section.title }}{% endblock %}
{% block content %}
<h1>{{ section.title }}</h1>
{% for story in story_list %}
<h2>
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}
`{{ section.title }}`在模板渲染时将会被变量的值替换,for标签可以实现模板的循环渲染。
基础语法
变量
变量实现从模板上下文字典(返回HTTP响应时传递过来的字典)中输出一个值,这是一个类似于dict的对象,包含键值对。当模板引擎遇到一个变量时,它会计算该变量,并用结果替换它。
变量名由字母、数字字符和下划线("_")组成,但不能以下划线开头。点(".")也出现在变量中,代表属性调用,变量名中不能有空格或标点符号。
示例:
django
My first name is {{ first_name }}. My last name is {{ last_name }}.
当传入一个上下文字典`{'first_name': 'John', 'last_name': 'Doe'}`时,将会渲染得到:
django
My first name is John. My last name is Doe.
模板中的变量被字典中的值替换了。
变量还可以使用点表示法实现字典查找、属性查找和列表索引查找等操作:
django
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
点表示法底层原理
当模板系统遇到一个点,它会按顺序尝试下面的动作:
1. 字典查询
2. 属性或方法查找
3. 数字索引查询
如果结果值是可调用的,则调用该值时将不带参数,调用的结果成为新的模板值。
当进行能覆盖字典查找的操作时,这种查找顺序可能会造成一些意想不到的行为。例如:如果试图循环一个collection .defaultdict字典对象:
django
{% for k, v in defaultdict.items %}
{其他操作}
{% endfor %}
因为字典查找是首先发生的,所以这个行为会先提供一个默认值,而不是使用预期的.items方法。在这种情况下,应该首先考虑使用字典查找,而不是使用字典的属性调用。
注意
属性通常被解释为一个文本字符串,防止和同名的变量冲突。例如{{foo.bar}}中的属性“bar”将被解释为一个文本字符串,如果模板上下文中存在变量“bar”,则不会使用该变量的值。
以下划线开头的变量属性可能不能访问,因为它们通常被认为是私有的。
如果引用不存在的变量,模板系统将插入string_if_invalid选项的值,该选项默认设置为“”(空字符串)。
标签
标签在模板渲染过程中提供任意逻辑。标签可以输出内容,作为控制结构,例如“if”语句或“for”循环,从数据库获取内容,甚至允许访问其他模板标签。
(1)标签声明
标签的一般形式为:
django
{% tag %}
示例:
django
{% csrf_token %}
(2)传入参数
django
{% cycle 'odd' 'even' %}
(3)成对使用的标签
有些标签需要开始和结束标签:
django
{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
(4)常用标签
for:循环数组中的每个元素. 比如, 显示列表 `athlete_list` 中每个元素的 `name` 属性。
django
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
if 、elif和else:在上面,如果athlete_list不为空,则{{athlete_list|length}}变量将显示运动员的数量。
否则,如果athlete_in_locker_room_list不为空,则会显示“Athletes should be out…”消息。如果两个列表都为空,则显示“No athletes”。
也可以在if标签里使用过滤器和各种操作符:
django
{% if athlete_list|length > 1 %}
Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
Athlete: {{ athlete_list.0.name }}
{% endif %}
注意
虽然上面的示例可以工作,但是要注意,大多数模板过滤器都返回字符串,因此使用过滤器进行数学比较通常不会正常工作,而长度是个例外。
(5)更多
Django有很多内置标签,更多关于内置标签的信息请参考官方文档:
https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/ref-templates-builtins-tags
如果需要编写自定义标签,请参考官方文档
https://docs.djangoproject.com/zh-hans/2.2/howto/custom-template-tags/howto-writing-custom-template-tags
如果需要对使用的标签和自定义的标签做一份说明文档,可以使用Django提供的文档工具,详情请参考:
https://docs.djangoproject.com/zh-hans/2.2/ref/contrib/admin/admindocs/
过滤器
简介
过滤器可以对变量做一些操作,例如给变量赋值,改变变量的值等。
修改变量显示
过滤器可以修改变量的显示。例如:
django
{{ name|lower }}
通过过滤器lower变量{{ name }}变为了小写字符,通过管道符(|)间隔变量和过滤器来使用过滤器。
链式调用过滤器
一个过滤器的输出可以作为下一个过滤器的输入。
{{ text|escape|linebreaks }}是一种常用的转换方式, 在这之后换行符被替换为了 <p> 标签。
转换变量和标签参数
过滤器转换变量和标签参数的值。示例:
django
{{ django|title }}
传入`{'django': 'the web framework for perfecalist With deadline '}`上下文字典时,该模板呈现为:
django
The Web Framework For Perfectionists With Deadlines
传入参数给过滤器
示例1:
django
{{ my_date|date:"Y-m-d" }}
my_date将会被替换为当前日期。
示例2:
django
{{ bio|truncatewords:30 }}
将会会显示 `bio` 变量的前30个字符
注意
过滤器参数中如果包含空格和标点符号,必须使用引号“”括起来,例如,要用逗号和空格连接列表,可以使用{{list|join:", "}}。
Django提供了大约60个内置模板过滤器,请参考官方文档:
https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/ref-templates-builtins-filters,
下面列举一些常用的过滤器:
default
如果变量为false或空,则使用给定的默认值。否则,使用变量的值。例如:
django
{{ value|default:"nothing" }}
如果 `value` 没有提供或者为空,那么将它显示为 "`nothing`" 。
length
返回值的长度。这对字符串和列表都适用。例如:
django
{{ value|length }}
如果 `value` 为 `['a', 'b', 'c', 'd']`, 那么他将被显示为 `4`。
filesizeformat
将值格式化为“人类可读的”文件大小(即“13kb”、“4.1 MB”、“102字节”等)。例如:
django
{{ value|filesizeformat }}
如果值为123456789,则输出为117.7 MB。
如果需要自定义过滤器,请参考请官方文档:
https://docs.djangoproject.com/zh-hans/2.2/howto/custom-template-tags/
注释
示例:
单行注释
django
{ this won't be rendered }
多行注释:{% comment %} 和{% endcomment %}
django
<p>Rendered text with {{ pub_date|date:"c" }}</p>
{% comment "Optional note" %}
<p>Commented out text with {{ create_date|date:"c" }}</p>
{% endcomment %}
注意:Comment标签不能嵌套使用。
作者简介:单雨,90后工科男,伪文艺青年。目前就读于北京理工大学宇航系,喜欢研究AI,网络爬虫,微信小程序以及机器人,痴迷于Coding,睡前必撸码。
【END】
直接写在template属性里面,这种写法比较直观,适用于html代码不多的场景,但如果html代码很多,就不方便维护了,所以如果代码多就不建议这么写:
在template属性里写模版id,这种和上面的写法很像,只不过单独把html的内容移到template标签里面,写起来就像正常的html一样,还有代码提示
在一个 <script> 元素中,并为其带上 text/x-template 的类型,然后通过一个 id 将模板引用过去
以上就是介绍的几种模版写法。
//别忘了引包
<body>
<div id="app-1">
{{msg}}
</div>
================
<div id="app-2">
{{msg}}
</div>
=================
<div id="app-3">
{{msg}}
</div>
<script>
//在vue.js中,可以使用template给元素添加模板,但是元素中只能有一个根元素,不能出现两个或两个以上的根同级元素。还可以在模板中绑定数据、表达式等。下面利用实例说明如何添加模板
// 创建 Vue 实例,得到 ViewModel
new Vue({
el: '#app-1',
data: {
msg:'这是通过el属性获取挂载元素的outerHTML方式渲染'
}
});
//结论:如果vue实例中有template属性,会将该属性值进行编译,将编译后的虚拟dom直接替换掉vue实例绑定的元素(即el绑定的那个元素);
//注意:template属性中的dom结构只能有一个根元素,如果有多个根元素需要使用v-if、v-else、v-else-if设置成只显示其中一个根元素;
new Vue({
el: '#app-2',
data: {
msg:'这是通过el属性获取挂载元素的outerHTML方式渲染'
},
template:'<div>这是template属性模板渲染</div>'
});
//render
new Vue({
el: '#app-3',
data: {
msg:'这是通过el属性获取挂载元素的outerHTML方式渲染'
},
template:'<div>这是template属性模板渲染</div>',
render: function(createElement){
return createElement('div',
// 参数2、这里相当于给标签加属性 例如:<div style='color:red,font-size: 14px'></div>
{
//给div绑定样式
style:{
width:'300px',
height:'400px',
color:'pink'
},
//给div绑定点击事件
on: {
click: () => {
console.log('点击事件')
}
}
},
// 参数3、参数中渲染的标签的子元素数组(可选)
// [
// // 文本节点直接写就可以
// 'text'
// ]
'这是render属性方式渲染。'
);
}
});
</script>
</body>
终极结论
el,template,render属性优先性
当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树,当选项对象中没有render渲染函数时,Vue构造函数首先通过将template模板编译生成渲染函数,然后再渲染DOM树,而当Vue选项对象中既没有render渲染函数,也没有template模板时,会通过el属性获取挂载元素的outerHTML来作为模板,并编译生成渲染函数。
换言之,在进行DOM树的渲染时,render渲染函数的优先级最高,template次之且需编译成渲染函数,而挂载点el属性对应的元素若存在,则在前两者均不存在时,其outerHTML才会用于编译与渲染。
*请认真填写需求信息,我们会在24小时内与您取得联系。