第五章  模板

  Django作为web框架,需要一种很便利的方法去动态地生成HTML网页,因此有了模板这个概念。模板包含所需HTML的部分代码以及一些特殊语法

  Django可以配置一个或多个模板引擎(甚至是0,如果不需要使用模板),模板系统有Django模板语言(Django Template Language, DTL)和Jinja2。Django模板语言是Django内置的模板语言,Jinja2是当前Python最流行的模板语言。

  

  5.1  变量与标签

  变量是模板中最基本的组成单位,模板变量是由视图函数生成的。如果变量没有被视图函数生成,那么模板引擎解析HTML时,模板变量不会显示在网页上。变量以{{ variable }}表示,variable是变量名,变量的类型可以是Python支持的数据类型,使用如下:

#  variable为字符串类型或整型,如variable = "Python"
{{ variable }}
# 输出Python # variable为字典或数据对象,通过点号(.)来访问其属性值
# 如variable = {"name": "Lily", "info": {"home": "BeiJing", "homeplace": "ShangHai"}}
{{ variable.name }}
# 输出Lily
{{ variable.info.home }}
# 输出BeiJing

  以MyDjango为例,抽取模板index.html的部分代码,代码如下:

<head>
<title>{{ title }}</title>
<meta charset="utf-8">
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static "css/hw_index.css" %}" >
<link rel="icon" href="{% static "img/hw.ico" %}">
<script src="{% static "js/hw_index.js" %}"></script>
</head> <ul id="cate_box" class="lf">
{% for type in type_list %}
<li>
<h3><a href="#">{{ type.type }}</a></h3>
<p>
{% for name in name_list %}
{% if name.type == type.type %}
<span>{{ name.name }}</span>
{% endif %}
{% endfor %}
</p>
</li>
{% endfor %}
</ul>

  上述代码分别使用模板的变量和标签,代码说明如下:

    1、{{  title  }}代表模板变量,从变量名title可以,变量的数据类型是字符串类型或整型。

    2、{%  load staticfiles  %}是模板的内置标签,load标签用于导入静态资源信息。

    3、{%  static "css/hw_index.css"  %}是模板是内置标签,static标签用于读取静态资源的文件内容。

    4、{%  for type in type_list  %}是for便利标签,将变量进行遍历输出。

    5、{%  if name.type == type.type  %}是if判断标签,主要对变量进行判断处理。

    6、{{  type.type  }}代表变量type_list的某个属性。

  从上面的例子可以看到,模板的变量需要和标签相互结合使用。模板的标签就如Python里面的函数和方法,Django常用的内置标签说明如下:

标签 描述
{%  for  %} 遍历输出变量的内容,变量类型应为列表或数据对象
{%  if  %} 对变量进行条件判断

{%  csrf_token  %}

生成csrf_token的标签,用于防护跨站请求伪造攻击
{%  url  %} 引用路由配置的地址,生成相应的URL地址

{%  with  %}

将变量名重新命名
{%  load  %} 加载导入Django的标签库
{%  static  %} 读取静态资源的文件内容
{%  extends  %} 模板继承,xxx为模板文件名,使当前模板继承xxx模板
{%  block xxx  %} 重写父类模板的代码

  在上述常用标签中,每个标签的使用方法都是各不相同的。使用如下:

#  for标签,支持嵌套,myList可以是列表或某个对象
# item可自定义命名,{% endfor %}代表循环区域终止符,代表这个区域的代码由标签for循环输出
{% for item in myList %}
{{ item }}
{% endfor %} # if标签,支持嵌套,判断条件符必须与变量之间使用空格隔开,否则程序会抛出异常
# {% endif %}与{% endfor %}的作用是相同的
{% if name == "Lily" %}
{{ name }}
{% elif name == "Lucy" %}
{{ name }}
{% else %}
{{ name }}
{% endif %} # url标签
# 生成不带变量的URL地址
# 相关的路由地址: path('', views.index, name='index')
# 字符串index是URL的参数name的值
<a href="{% url 'index' %}" target="_blank">首页</a>
# 生成带变量的URL地址
# 相关的路由地址:path('search/<int:page>.html', views.search, name='search')
# 字符串search是URL的参数name的值,1是URL的变量page的值
<a href="{% url 'search' 1 %}" target="_blank">第一页</a> # total标签
{% with total = products_total %}
{{ total }}
{% endwith %} # load标签,导入静态文件标签库staticfiles,staticfiles来自settings.py的INSTALLED_APPS
{% load staticfiles %} # static标签,来自静态文件标签库staticfiles
{% static "css/hw_index.css" %}

  在for标签中,模板还提供一些特殊的变量来获取for标签的循环信息,变量说明如下:

变量 描述
forloop.counter 获取当前循环的索引,从1开始计算
forloop.counter() 获取当前循环的索引,从0开始计算
forloop.revcounter 索引从最大数开始递减,直到索引到1位置
forloop.revcounter() 索引从最大数开始递减,直到索引到0位置
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop 在嵌套的for循环中,获取上层for循环的forloop

  上述变量来自于forloop对象,该对象是模板引擎解析for标签时所生成的。下面是使用方法:

{%  for name in name_list  %}
{% if forloop.counter == 1 %}
<span>这是第一次循环</span>
{% elif forloop.last %}
<span>这是最后一次循环</span>
{% else %}
<span>本次循环次数为: {{ forloop.counter }}</span>
{% endif %}
{% endfor %}

  5.2  模板继承

  模板继承是通过模板标签来实现的,其作用是将多个HTML模板的共同代码集中在一个新的HTML模板中,然用户各个模板可以直接调用新的HTML模板,从而生成HTML网页,这样可以减少模板之间重复的代码。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<a href="{% url 'index' %}" target="_blank">首页</a>
<h1>Hello Django</h1>
</body>
</html>

  上述代码是一个完整的HTML模板,一个完整的模板有<html>和<body>两大部分,其中<html>部分在大多数情况下都是相同的,因此可以将<html>部分写道共用模板中,将共用模板命名为base.html,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>

  在base.html的代码中可以看到,<body>里的内容变为{% block body %}{% endblock %},block标签相当于一个函数,body是对该函数的命名,开发者可自行命名。在一个模板中可以添加多个block标签,只要每个block标签的命名各不相同即可。接着在模板index.html中调用共用模板base.html,代码如下:

{% extends "base.html" %}
{% block body %}
<a href="{% url 'index' %}" target="_blank">首页</a>
<he>Hello Django</he>
{% endblock %}

  模板index.html调用共用模板base.html的实质是有模板继承实现的,调用步骤如下:

    1、在模板index.html中使用{% extends "base.html" %}来继承模板base.html的代码。

    2、由标签{% block body %}在继承模板的基础上实现自定义模板的内容。

    3、由{% endblock %}结束block标签。

  从index.html看到,模板继承与Python的类继承的原理是一致的,通过继承的方式使其具有父类的功能和属性,然后以重写的方式实现各种开发需求。

  5.3  自定义过滤器

  过滤器主要是对变量的内容进行处理,如替换、反序和转义等。通过过滤器处理变量可以将变量的数据格式和内容转换为我们想要的效果,而且相应减少视图函数的代码量。过滤器的使用方法如下:

{{  variable  |  filter  }}

  模板引擎解析带过滤器的变量时,首先过滤器filter处理变量variable,然后将处理后的变量显示在网页上。其中,variable代表模板变量,管道符号" | "代表变量使用过滤器,filter代表某个过滤器。变量可以支持多个过滤器同时使用,例如:

{{  variable  |  filter  |  lower  }}

  在使用的过程中,有些过滤器还可以传入参数,但仅支持一个参数的传入。带参过滤器的使用方法如下:

{{  variable  |  date:"D d M Y"  }}

  Django为开发者内置过滤器如下:

内置过滤器 使用形式 说明
add {{  value | add: "2"  }} 将value的值增加2
addslashes   {{  value | addslashes  }} 在value中的引号前增加反斜线 
capfirst   {{  value | capfirst  }} value的第一个字符转化成大写形式 
cut   {{  value | cut:arg  }} 从value中删除所有arg的值。如果value是"String with spaces", arg是" ",那么输出的是"Stringwithspaces" 
date   {{  value | date:"D d M Y"  }} 将日期格式数据按照给定的格式输出 
default   {{  value | default:"nothing"  }} 如果value的意义是False,那么输出值为过滤器设定的默认值 
default_if_none   {{  value | default_if_none:"nothing  }} 如果value的意义是None,那么输出值为过滤器设定的默认值 
dictsort   {{  value | dictsort:"name"  }} 如果value的值是一个列表,里面的元素是字典,那么返回值按照每个字典的关键字排序 
dictsortreversed   {{  value | dictsortreversed:arg  }} 如果value的值是一个列表,里面的元素是字典,每个字典的关键字反序排行
divisibleby   {{  value | divisibleby:arg  }} 如果value能够被arg整除,那么返回值将是True 
escape   {{  value | escape }} 控制HTML转义,替换value中的某些HTML特殊字符 
escapejs   {{  value | escapejs}} 替换value中的某些字符,以适应JavaScript和JSON格式 
filesizeformat   {{  value | filesizeformat  }} 格式化value,使其成为易读的文件大小,例如13KB、4.1MB等 
first   {{  value | first  }} 返回列表中的第一个Item,例如,如果value是列表['a','b','c'],那么输出将是'a' 
floatformat   {{  value | floatformat   }}{{  value | floatformat:arg   }} 对数据进行四舍五入处理,参数arg是保留小数位,可以是正数或负数,如{{  value | floatformat:"2"  }}是保留两位小数。若无参数arg,默认保留1位小数,如{{  value | floatformat  }} 
get_digit   {{  value | get_digit:"arg"   }} 如果value是123456789,arg是2,那么输出的是8 
iriencode   {{  value | iriencode   }} 如果value中有非ASCII字符,那么将其转化成URL中适合的编码 
join   {{  value | join:"arg"}}

使用指定的字符串连接一个list,作用如同Python的str.join(list)

last   {{  value | last  }} 返回列表中的最后一个Item 
length   {{  value | length  }} 返回value的长度 
length_is   {{  value | length_is:"arg"  }} 如果value的长度等于arg,例如:value是['a','b','c'],arg是3,那么返回True 
linebreaks   {{  value | linebreaks  }} value中的"\n"将被<br/>替代,并且将整个value使用<p>包围起来,从而适合HTML的格式 
linebreaksbr   {{  value | linebreaksbr  }} value中的"\n"将被<br/>替代 
timeuntil  {{  value | timeuntil  }} 返回value距离当前日期的天数和小时数
linenumbers   {{  value | linenumbers  }}  为显示的文本添加行数
ljust   {{  value | ljust  }} 以左对齐方式显示value 
center   {{  value | center  }} 以居中对齐方式显示value 
rjust   {{  value | rjust  }} 以右对齐方式显示value 
lower   {{  value | lower  }}  将一个字符串转换成小写形式
make_list   {{  value | make_list  }} 将value转换成list。例如value是Joel,输出[u'J',u'o',u'e',u'l'];如果value是123,那么输出是[1,2,3] 
pluralize 

{{  value | pluralize  }}或 {{  value | pluralize:" es "  }}

或 {{  value | pluralize:"y,ies  }}

将value返回英文复数形式 
random   {{  value | random  }} 从给定的list中返回一个任意的Item 
removetags   {{  value | removetags:"tag1 tag2 tag3..."  }} 删除value中tag1,tag2...的标签 
safe   {{  value | safe  }} 关闭HTML转义,告诉Django这段代码是安全的,不必转义 
safeseq   {{  value | safeseq  }} 与上述safe基本相同,但有一点不同;safe针对字符串,而safeseq针对多个字符串组成的sequence 
slice   {{  some_list | slice:":2"  }} 与Python语法中的slice相同,":2"表示截取前两个字符,此过滤器可用于中文或英文 
slugify   {{  value | slugify  }} 将value转换成小写形式,同时删除所有分单词字符,并将空格变成横线。例如:value是Joel is a slug,那么输出的将是joel-is-a-slug 
striptags   {{  value | striptags  }} 删除value中的所有HTML标签 
time   {{  value | time:"H:i"  }}或{{  value | time  }} 格式化时间输出,如果time后面没有格式化参数,那么输出按照默认设置的进行 
truncatewords   {{  value | truncatewords:2  }} 将value进行单词截取处理,参数2代表截取前两个单词,此过滤器值可用于英文截取。如value是Joel is a slug那么输出将是:Joel is 
upper   {{  value | upper  }} 转换一个字符串为大写形式 
urlencode   {{  value | urlencode  }} 将字符串进行URLEncode处理 
urlize   {{  value | urlize  }} 将一个字符串中的URL转换成可点击的形式。如果value是Check out www.baidu.com,那么输出的将是:Check out <a href="http://www.baidu.com">www.baidu.com</a> 
wordcount   {{  value | wordcount  }} 返回字符串中单词的数目 
wordwrap   {{  value | wordwrap:5  }} 按照指定长度的分割字符串 
timesince   {{  value | timesince:arg  }} 返回参数arg到value的天数和小时数。如果arg是一个日期实例,表示2006-06-01午夜,而value表示2006-06-01早上8点,那么输出结果返回"8 hours" 

  在实际开发中,如果内置过滤器的功能不太适合实际开发需求,我们可以通过自定义过滤器来解决问题。首先在MyDjango中添加文件和文件夹,如下图:

  从图中看到,在MyDjango项目中添加了user_defined文件夹,在其文件夹下又分别添加了templatetags文件夹和__init__.py文件。templatetags用于存放自定义过滤器的代码文件,该文件夹也可以存放在项目的APP中,但必须注意的是,文件夹的命名必须为templatetags,否则Django在运行的时候无法识别自定义过滤器。最后在templatetags文件夹下创建myfilter.py文件,该文件是编写自定义过滤器的实现代码。

  完成过滤器的目录搭建,接着是配置过滤器的信息,在配置文件settings.py的INSTALLED_APPS里面添加user_defined。当项目启动时,Django会从INSTALLED_APPS的配置中查找过滤器,若过滤器设置在index的目录下,则只需在INSTALLED_APPS中配置index即可,如下:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
'user_defined',
]

  完成上述两个环境配置后,下一步是编写自定义过滤器的实现代码,在myfilter.py中添加以下代码:

from django import template
# 注册过滤器
register = template.Library()
# 声明并定义过滤器
@register.filter
def myreplace(value, agrs):
oldValue = agrs.split(':')[0]
newValue = agrs.split(':')[1]
return value.replace(oldValue, newValue)

  上述代码用于实现HTML模板的字符串替换功能,与Python的replace函数相同,过滤器说明如下:

    1、首先导入模板功能template,通过template声明Library对象,将对象赋值给变量register,这一过程称为注册过滤器。

    2、过滤器以函数的形式实现,在函数前使用register.filter装饰器来表示该函数是一个过滤器,函数名可自行命名。

    3、函数参数可设置一个或两个,如上述的参数分别是value和agrs,参数value是HTML模板的变量,参数agrs是过滤器函数定义的函数参数。

    4、过滤器函数最后必须将处理结果返回,否则在使用过程中会出现异常信息。

  最后在HTML模板中使用我们自定义的过滤器,以index.html模板的title为例,代码如下:

{% load myfilter %}
<!DOCTYPE html>
<html>
<head>
<title>{{ title|myreplace:'首页:我的首页' }}</title>
<meta charset="utf-8">
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static "css/hw_index.css" %}" >
<link rel="icon" href="{% static "img/hw.ico" %}">
<script src="{% static "js/hw_index.js" %}"></script>
</head>

  在HTML模板中使用自定义的过滤器可以分为两大步骤,说明如下:

    1、{%  load myfilter  %}用于导入templatetags文件夹的myfilter.py文件中所定义的功能,用来告诉Django在那个地方可以找到自定义过滤器。

    2、{{  title | myreplace:'首页:我的首页'  }}把变量title含有"首页"的内容替换成"我的首页"。其中,myreplace是过滤器的函数名,”首页:我的首页"是函数参数agrs的值,函数参数value的值为模板变量title的值。运行结果如下:

  5.4  本章小结

  Django作为Web框架,需要一种很便利的方法去动态地生成HTML网页,因此有了模板这个概念。模板包含所需HTML的部分代码以及一些特殊的语法,特殊的语法用于描述如何将数据动态插入HTML网页中。模板语言中主要在HTML文件中编写,大概分为三类:变量/标签和过滤器。三者说明如下:

    1、变量是将视图函数传递的数据作用在模板文件上,通过模板引擎将数据转换并生成HTML网页。

    2、标签可以理解为代码编程里面的函数功能,常用的标签有控制循环、条件判断和模板继承等。

    3、过滤器主要是对变量的数据进行处理,如替换、反序和转义等。

  模板继承与Python的类继承的原理是一致的,通过继承的方式使其具有父类的功能和属性,然后以重写的方式实现各种开发需求。模板继承的实现步骤如下:

    1、在模板index.html中使用{%  extends "base.html"  %}来继承模板base.html的代码。

    2、由标签{%  block body  %}在继承模板的基础上实现自定义模板的内容

    3、由{%  endblock  %}结束block标签

  过滤器主要是对变量的内容进行处理,如替换、反序和转义等。通过过滤器处理变量可以将变量的数据格式和内容转化为我们想要的效果,而且想要减少视图函数的代码量。过滤器的使用方法如下:

{{  variable | filter  }}

  模板引擎解析带过滤器的变量时,首先过滤器filter处理变量variable,然后将处理后的变量显示在网页上。其中,variable代表模板变量,管道符号"|"代表变量使用过滤器,filter代表某个过滤器。变量可以支持多个过滤器同时使用,例如:

{{  variable | filter | lower  }}

  在使用的过程中,有些过滤器还可以传入参数,但仅支持一个参数的传入。带参过滤器的使用方法如下:

{{  variable |  date:"D d M Y"  }}

玩转Django2.0---Django笔记建站基础五(模板)的更多相关文章

  1. django笔记 - 建站

    1,建站步骤:1)django-admin.exe startproject mysite 创建完后的目录结构: - mysite # 对整个程序进行配置 - init - settings # 配置 ...

  2. 玩转Django2.0---Django笔记建站基础十二(Django项目上线部署)

    第十二章 Django项目上线部署 目前部署Django项目有两种主流方案:Nginx+uWsGI+Django或者Apache+uWSGI+Django.Nginx作为服务器最前端,负责接收浏览器的 ...

  3. 玩转Django2.0---Django笔记建站基础十三(第三方功能应用)

    第13章 第三方功能应用 在前面的章节中,我们主要讲述Django框架的内置功能以及使用方法,而本章主要讲述Django的第三方功能应用以及使用方法.通过本章的学习,读者能够在网站开发过程中快速开发网 ...

  4. 玩转Django2.0---Django笔记建站基础十(二)(常用的Web应用程序)

    10.3 CSRF防护 CSRF(跨站请求伪造)也成为One Click Attack或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用,窃取网站的用户信息来制作 ...

  5. 玩转Django2.0---Django笔记建站基础十(一)(常用的Web应用程序)

    第十章 常用的Web应用程序 Django为开发者提供了常见的Web应用程序,如会话控制.高速缓存.CSRF防护.消息提示和分页功能.内置的Web应用程序大大优化了网站性能,并且完善了安全防护机制,而 ...

  6. 玩转Django2.0---Django笔记建站基础六(模型与数据库)

    第六章 模型与数据库 Django对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite和Oracle,而且为这些数据库提供了统一的调用API,这些API统称为ORM框架. ...

  7. 玩转Django2.0---Django笔记建站基础四(视图)

    第四章 视图 4.1 探究视图 一.视图说明 视图(View)是Django的MTV架构模式的V部分,主要负责处理用户请求和生成相应的相应部分,然后在页面或其它类型文档中显示.也可以理解为视图是MVC ...

  8. 玩转Django2.0---Django笔记建站基础十一(二)((音乐网站开发))

    11.5 歌曲排行榜 歌曲排行榜是通过首页的导航链接进入的,按照歌曲的播放次数进行降序显示.从排行榜页面的设计图可以看到,网页实现三个功能:网页顶部搜索.歌曲分类筛选和歌曲信息列表,其说明如下: 1. ...

  9. 玩转Django2.0---Django笔记建站基础十一(一)(音乐网站开发)

    第十一章 音乐网站开发 本章以音乐网站项目为例,介绍Django在实际项目开发中的应用,该网站共分为6个功能模块分别是:网站首页.歌曲排行榜.歌曲播放.歌曲点评.歌曲搜索和用户管理. 11.1 网站需 ...

随机推荐

  1. AutoHotKey 用打码的快捷键

    本文告诉大家如何使用 AutoHotKey 将 - 键默认输入的时候是下划线,因为使用下划线在写代码的时候是用在私有字段,而 - 很少使用 我打码经常需要使用下划线_而下划线需要按shift+- 两个 ...

  2. easypermissions拒绝权限后闪退。 java.lang.NoSuchMethodError: No virtual method isStateSaved()Z in class Landroid/support/v4/app/FragmentManager

    Process: com.tazan.cd.streetlight, PID: 18825 java.lang.NoSuchMethodError: No virtual method isState ...

  3. Java Developer's Guide to SSL Certificates

    https://www.codebyamir.com/blog/java-developers-guide-to-ssl-certificates Overview When developing w ...

  4. struts2生成随机验证码图片

    之前想做一个随机验证码的功能,自己也搜索了一下别人写的代码,然后自己重新用struts2实现了一下,现在将我自己实现代码贴出来!大家有什么意见都可以指出来! 首先是生成随机验证码图片的action: ...

  5. SpringBoot-Swagger整合zuul智能列表

    SpringBoot-Swagger整合zuul智能列表 简介 可能大家都有用过swagger,可以通过ui页面显示接口信息,快速和前端进行联调. 现在基本都是多模块微服务化,每个服务都有这样的ui页 ...

  6. eclipse中SSM(maven)项目搭建全过程+实现用户登录功能

    项目创建之前确保eclipse中已经配置好了jdk,tomcat,maven如果没有配置下面有配置教程的链接   eclipse中配置jdk的教程url:http://www.cnblogs.com/ ...

  7. CodeForces - 1228D

    乍一看,嗯,图论题,不错: 结果,这尼玛是模拟???? 传送链接:https://codeforces.com/contest/1228/problem/D 看了大佬的代码瞬间就明白了许多!!! #i ...

  8. 超详细!如何利用Huginn制作专属RSS

    前言 本文首发于个人网站,欢迎订阅.本篇博文接上利用Feed43为网站自制RSS源,上一篇讲解了RSS的简介以及利用Feed43自制专属RSS,Feed43有其优势,缺陷也很明显,不能高度自定义.有的 ...

  9. Python学习(三)基础

    一.函数与模块 定义函数: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 (). 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数. 函数的第一行语句可以选择性地使用 ...

  10. 记一次买4K显示器的心酸历程

    由于最近在 B 站直播的次数有点多,还有就是平时录制的视频也有点人看了,所以想多做点视频发布到 B 站上面,但是自己看了以前的视频,发现视频确实画面确实粗糙,不仅仅是视频不清晰的原因,更主要的是我眼睛 ...