Django框架——基础之模板系统(template文件夹) 1. 常用语法 2. 变量 3. Filters(过滤器) 4. Tags(逻辑标签) 5. 母版(模板) 6. 组件 7. 静态文件相关 8. tag

Django框架——基础之模板系统(template文件夹)
1. 常用语法
2. 变量
3. Filters(过滤器)
4. Tags(逻辑标签)
5. 母版(模板)
6. 组件
7. 静态文件相关
8. tag

---恢复内容开始---

需要记住两组特殊符号:{{  }}  和 {%  %}

在运用到变量的时候使用{{  }},如果是跟逻辑相关的话就使用{%  %}。

在Django模板(template)中,会使用到的{{  }}  和 {%  %}写法,在专业中就称之为Django的 “ 模板语言 ” 

2. 变量

在Django模板中,使用的变量的时候,就是用这个格式:{{ 变量名 }}。

在template模板引擎遇到一个变量的时候,它自动根据python后台中的views模块提供的相关数据,计算出这个变量的结果,并用这个结果替换掉它自己。

变量命名:命名规则包含(字符、数字、下划线)的组合。

注意:变量的名称一定不能含有空格、标点符号。

点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的查询优先级:

第一:字典查询(Dictionary lookup)

第二:属性或方法查询(Attribute or method lookup)

第三:数字索引查询(Numeric index lookup)

注意事项:

  1. 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。
  2. 如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串) 。

变量的使用写法:

{# 取list列表中的第一个参数 #}
{{ list.0 }}

{# 取d字典中key的值 #}
{{ d.name }}

{# 取对象的name属性 #}
{{ person_list.0.name }} {# (大白话:人对象的列表  第一个人对象 的 名字)," . "点跟"的”有些类似#}
{# .操作只能调用不带参数的方法 #} {{ person_list.0.eat }}

注意:如果是调用方法的话,后面也不能带括号()。

3. Filters(过滤器)

在Django的模板语言中,通过使用过滤器来改变变量的显示(结果)。

过滤器的语法:{{ name|filter_name:参数 }}。注意:使用管道符 ” | “ name就是变量的结果,其实就是变量名。

例如:在模板中的一个变量使用如下{{ name|lower}}会将name变量通过length过滤(操作)之后再显示它的值。lower在这里的作用是将文本全都变成小写。

注意事项:

  1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入 。
  2. 过滤器可以接受参数。例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
  3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
  4. '|'左右没有空格没有空格没有空格

3.1 default

例如:{{ name|default:"not found" }}

如果变量name的值是false或者为空或者不存在,该处自动被默认值not found字符串代替,或者说此处的变量名的值自动为"not found" 。

3.2 length

例如:{{ name|length}}

返回变量name的值的长度,作用于字符串和列表。

如果上面的name=[1, 2, 3, 4, 5, 6],那上面得到的值就是6.

3.3 filesizeformat

 例如:{{ name|filesizeformat }}

将name的值进行格式化,也就是说,将一个文件的大小进行自动转换成为,我们平时生活中能够理解的格式!(例如:“ 20MB ”,“ 20KB ”,“ 20GB ” 等等)

如果name的值是123456789,输出的将会是117.7MB。

3.4 slice

 例如:{{ name_list|slice:":2" }

返回列表的一部分。也就是切片,与Python的列表切片相同的语法。

如果name_list = ["张三", "李四", "王五", "老六"],那上面的结果将会得到["张三", "李四"]

3.5 date

根据给定格式对一个日期变量进行格式化。

可用的格式字符串:

格式化字符 描述 示例输出
a 'a.m.'或'p.m.' 'a.m.'
A 'AM'或'PM' 'AM'
b 月份,文字形式,3个字母,小写。 “jan”
B 未实现。  
c ISO 8601格式 2008-01-02T10:30:00.000123+02:00
d 月的日子,带前导零的2位数字。 '01'到'31'
D 周几的文字表述形式,3个字母。 'Fri'
e 时区名称 '','GMT','-500','US/Eastern'等
E 月份,分地区。  
f 时间 '1','1:30'
F 月,文字形式。 'January'
g 12小时格式,无前导零。 '1'到'12'
G 24小时格式,无前导零。 '0'到'23'
h 12小时格式。 '01'到'12'
H 24小时格式。 '00'到'23'
i 分钟 '00'到'59'
I 夏令时间,无论是否生效。 '1'或'0'
j 没有前导零的月份的日子。 '1'到'31'
l 星期几,完整英文名 'Friday'
L 布尔值是否是一个闰年。 True或False
m 月,2位数字带前导零。 '01'到'12'
M 月,文字,3个字母。 “Jan”
n 月无前导零。 '1'到'12'
N 美联社风格的月份缩写。 'Jan.','Feb.','March','May'
o ISO-8601周编号 '1999'
O 与格林威治时间的差,单位小时。 '+0200'
P 时间为12小时 '1 am','1:30 pm','midnight','noon','12:30 pm'>
r RFC 5322格式化日期。 'Thu, 21 Dec 2000 16:01:07 +0200'
s 秒,带前导零的2位数字。 '00'到'59'
S 一个月的英文序数后缀,2个字符。 'st','nd','rd'或'th'
t 给定月份的天数。 28 to 31
T 本机的时区。 'EST','MDT'
u 微秒。 000000 to 999999
U 自Unix Epoch以来的秒数(1970年1月1日00:00:00 UTC)。  
w 星期几,数字无前导零。 '0'(星期日)至'6'(星期六)
W ISO-8601周数,周数从星期一开始。 1,53
y 年份,2位数字。 '99'
Y 年,4位数。 '1999'
z 一年中的日子 0到365
Z 时区偏移量,单位为秒。 -43200到43200

例如:{{ name|date:"Y-m-d H:i:s"}}

如果name是一个datetime对象,比如datetime.datetime.now(),输出将是字符串 ' 2017-08-30 11:08:29 ' 。

可以将date与time过滤器结合使用,以呈现datetime值的完整表示形式。 例如:

{{ value|date:"D d M Y" }} {{ value|time:"H:i" }}

3.6 safe

 例如:

  {{ name|safe }}

将字符串标记为安全,不需要转义。

详解:

  Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不i必转义。

如果这里的name的值为name= "<a href='http://www.baidu.com/'>点我进入百度</a>"。这个时候,这里的点我将会成为一个定向百度链接的超级链接,也就是说只要点击" 点我进入百度 "就可以跳转到百度页面!

3.7 truncatechars

例如:
  {{ name|truncatechars:9 }}
参数:截断之后剩下的字符数

如果字符串包含的字符总个数多于指定的字符数量,那么会被截断掉后面的部分。截断的字符串将以“...”结尾,注意结尾中的 ”...“ 算三个字符

如果这里的name的值是 “my name is xxxx”,那上面输出的结果是:my nam...

3.8 truncatewords

例如:

  {{ name|truncatewords:2 }}

 在一定数量的字数后截断字符串。与truncatechars不同的是,这个以字的个数计数而不是字符计数。截断的字符串将以“...”结尾,注意结尾中的 ”...“ 在这里不算三个字符了

如果这里的name的值还是“my name is xxxx” ,那上面输出的结果是:my name...

3.9 cut

例如:

{{ name|cut:"," }}

移除name中所有的与给定参数相同的字符串。这里的是意思是:移除name的值中,存在的逗号 ”,"。

如果name的值是为“my,name,is,xxxx”,输出将为"Smynameisxxxx"。

3.10 join

例如:{{ name|join:"//" }} 

使用字符串连接列表,类似Python的str.join(list)

如果上面的name=["aa", "bb", "cc"],在带入上面变量之后得到的结果就是:aa//bb//cc。

注意:如果name是字典的话,例如:name={"aaa": 111, "bbb": 222},结果为key的链接,即得到的结果为:aaa//bbb

3.11 timesince

传入的时间对象(blog_date)跟当前的时刻的时间(comment_date)的一个时间差,用于写多长时间之前。说白了,这个就是计算两个时间的时间差(comment_date — blog_date)。

时间的差值被Django自动换算,可以表示(例如,“4天,6小时”)。

例如:{{ blog_date|timesince:comment_date }}

3.12 timeuntil

类似于timesince,它测量从现在开始直到给定日期或日期时间的时间。例如,如果今天是2006年6月1日,而conference_date是2006年6月29日,则{{ conference_date | timeuntil }}将返回“4 weeks”。

可选参数是一个包含用作比较点的日期变量。如果from_date为2006年6月22日,则以下内容将返回“1 weeks”:

{{ conference_date|timeuntil:from_date }}

3.13 自定义filter

自定义的filter(过滤器)可以分为三大步骤:首先是前期步骤,然后是编辑filter过滤器,最后是使用自定义filter过滤器

首先,自定义filter前期步骤:

  1.  在app中新建一个templatetags名字固定,不能变,只能是这个),和views.py、models.py等文件处于同一级别目录下。这是一个python包!所以,一定不要忘记这个包的里面是要有__init__.py文件的,因为__init__.py文件是以使得该目录可以作为Python的包的条件。

  2.  在添加templatetags包后,需要重新启动项目,然后才能在模板中使用标签或过滤器。

  3.  在templatetages包里,创建自定义过滤器的模块。

    a    将你自定义的标签和过滤器将放在templatetags包下的一个模块里。

    b    这个模块的名字是后面载入标签时使用的标签名,所以要谨慎的选择名字以防与其他应用下的自定义标签和过滤器名字冲突,当然更不能与Django内置的冲突。

    假设你自定义的标签/过滤器在一个名为app01_myfilter.py的文件中,那么你的app目录结构看起来应该是这样的:

app01/
    __init__.py
    models.py
    templatetags/        # templatetags包
        __init__.py
        app01_myfilter.py    # 创建存放自定义filter(过滤器)的文件
    admin.py
    apps.py
    views.py

然后,是编写自定义filter过滤器:

  app01_myfilters.py文件代码如下:步骤是  1  >>  2  >>  3

# 1.  首先需要引入template模块,并创建一个library注册对象
from django import template
register = template.Library()


# 2.  接着才是正式编辑filter

@register.filter(name="addsb")    # 3.  注册filter(filter的别名为addsb):写好下面的自定义filter函数后,需要注册过滤器,用装饰器函数形式即可
def add_sb(value):                        # 定义不带参数的自定义filter函数
    return "{} SB.".format(value)    

@register.filter(name="add_str")      # 3.  注册filter(filter的别名为add_str):同上   
def add_str(value, arg):        # 定义带一个参数的自定义filter
    return "{} {}.".format(value, arg)

#  注意:第一个参数(value)永远是管道符前面那个变量,第二个以后才是参数    

最后,是使用自定义filter过滤器

  1.   需要在template模块下面的模板中,引入自定义过滤器的文件模块如下:

    {% load app01_myfilters %}

  2.  结合变量使用自定义的filter过滤器  

    <p>不带参数自定义filter:{{ myname|addsb }}</p>

    <p>带参数的自定义filter:{{ myname|addstr:"牛逼" }}</p>

        解析:管道符 ” | “ 的左边的myname是views.py模块提供的变量,右边的addsb是自定义的filter过滤器,而冒号 ” : “的右边则是自己写的参数。

    如果myname的值为 myname = "my name is" 

    带入上面的的自定义filter过滤器后结果如下:

      不带参数自定义filter:my name is sb.

      带参数的自定义filter:my name is 牛逼.

创建自定义的filter过滤器简单步骤:

  第一.  首先创建templatetags python包,接着重新启动项目,最后创建用于存放自定义filter过滤器的.py文件

  第二.  首先引入django下面的template模块,接着编写自定义的filter过滤器函数,最后使用装饰器的形式注册过滤器函数,并通过name定义过滤器的名称(过滤器函数的别名)

  第三.  首先,在模板语言中,使用{% load 自定义filter名称%}引入自定义filter过滤器,接着在引入的下面开始使用过滤器即可。

3.14

3.15

3.16

4. Tags(逻辑标签)

4.1 for循环

普通for循环

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% endfor %}
</ul>

for循环可用的一些参数:

 

Variable Description
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环

for ... empty for循环

当下面的user_list里面的内容为空,或者user_list根本不存在的时候,for循环会自动跳转到empty程序块,并且执行(如果是下面的话就是得到:空空如也)。
Django框架——基础之模板系统(template文件夹)
1. 常用语法
2. 变量
3. Filters(过滤器)
4. Tags(逻辑标签)
5. 母版(模板)
6. 组件
7. 静态文件相关
8. tag
<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>
Django框架——基础之模板系统(template文件夹)
1. 常用语法
2. 变量
3. Filters(过滤器)
4. Tags(逻辑标签)
5. 母版(模板)
6. 组件
7. 静态文件相关
8. tag

4.2 if判断

if……else  语句

{% if user_list|length > 5 %}
    用户数超过5人
{% else %}     
    用户数小于等于5人,或没有用户
{% endif %}

if……elif……else语句

Django框架——基础之模板系统(template文件夹)
1. 常用语法
2. 变量
3. Filters(过滤器)
4. Tags(逻辑标签)
5. 母版(模板)
6. 组件
7. 静态文件相关
8. tag
{% if user_list %}
  用户人数:{{ user_list|length }}
{% elif black_list %}
  黑名单数:{{ black_list|length }}
{% else %}
  没有用户
{% endif %}

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

4.3 with语句

 当一个变量很长很复杂的时候,定义一个中间变量,多用于给一个复杂的变量起别名。

例如一个名字的列表name_list2 = [['张三0', '李四0', '王五0'], ['张三1', ['张三1.1', '李四1.1', '王五1.1'], '王五1']]
当我们要取 " 李四1.1 " 的时候,就是 " name_list2.1.1.1 "这个时候就觉得 name_list2.1.1.1比较长,
而在某个模板语言的某个程序块中会一直用到这个,所以我们需要给它起一个别名,主要目的是为了方便操作

起别名的方法有一下两种方式

注意:等号左右不要加空格。


{% with total=name_list2.1.1.1%} 
  {{ total }} with语法{{ total|pluralize }}
{% endwith %}


{% with name_list2.1.1.1 as total %} 
  {{ total }} with语法{{ total|pluralize }}
{% endwith %}

4.4 csrf_token

这个标签用于跨站请求伪造保护。

在页面的form表单里面写上{% csrf_token %}

4.5 注释

{# 注释内容... #}

4.6 模板语言使用注意事项

1. Django的模板语言不支持连续判断,即不支持以下写法:

{% if a > b > c %}
...
{% endif %}

2. Django的模板语言中属性的优先级大于方法

def xx(request):
    d = {"a": 1, "b": 2, "c": 3, "items": "100"}
    return render(request, "xx.html", {"data": d})

如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:

{{ data.items }}

默认会取d的items key的值。

5. 母版(模板)

 注意:我们通常会在母板中定义页面专用的CSS块和JS块,方便子页面替换。

5.1继承母版

 在子页面中的第一行代码必须使用下面的语法来继承母版,其中base.html是母版文件!

{% extends 'base.html' %}

5.2母版与继承母版的注意事项:

1.子页面中的继承母版的语句一定要放在第一行!

2.{% extends 'base.html' %},继承语法中的母版名称位置,是有引号的

3.在母版文件base,html中,是会定义很多块(block)的,但是我们会固定的另外定义page-js和pafe-css两个块

4.在view.py中的对应关系的函数,返回的是子页面的!!而不是母版哦!!!

5.3块(block)

 在母版中使用块的语法定义:{% block page-main %} …………{% endblock % }。块的名字:page-main

例如:这条语句已经在木板文件中定义了。那接下这子页面中的应用如下:

//子页面中对应母版的块的定义
{% block page-main %}     //首尾语法与母版中一模一样

<div class="content">
   <
p>  我想写一首诗<br/></p> <p>  记录我对你的思念</p> <p>  我想写一首诗</p> <p>  记下这痛苦的瞬间</p> <p>  我想写一首诗</p> <p>  记住这惨痛的教训</p> <p>  我想唱一曲歌</p> <p>  唱出我思念你时的情怀</p> <p>  我想唱一首歌</p> <p>  唱到我幻想的浪漫深处</p> <p>  我想唱一支歌</p> <p>  歌颂我对你的痴情</p> <p>  可惜怯懦的我哽咽着哭泣,始终没拿起也没放弃</p> <p>  春光抚摸着我的爱意</p> <p>  夏日打击着我的冲动</p> <p>  秋风嘲讽着我的深情</p> <p>  冬雪将我的躯干冰封</p> <p>  我无力挣扎,挣扎,挣扎</p> <p>  直到春暖融尽这刺骨的冰霜</p> <p>  夏炎炙烤着我的肢体</p> <p>  秋愁撕裂着我的心府</p> <p>  冬魔蚕食着我的生命</p> <p>  几番风雨,几多痴迷,几度春秋……</p> <p>  啊!彩虹,那么近,那么亮</p> <p>  别告诉我那是地狱之火,我要去天堂;</p> <p>  别对我说那是天堂之光</p> <p>  错了,我将留在这惨痛的人间!</p> <p>  去地狱的是佛,上天堂的是仙,我是人,却不愿留在虚伪的凡间</p> <p>  我一直走,走,走</p> <p>  没有尽头,决不回头,只期盼有一天能碰头……</p> </div> {% endblock %} //首尾语法与母版中一模一样

5.4 为什么要有模板和继承?

把多个页面公用的部分提取出来,放在一个 母版 里面。
其他的页面只需要 继承 母版就可以了。

5.5 使用模板的基本步骤:

1.把所有THML网页的公用(相同部分)提取出来,一同放到母版文件中,(一般来说母版文件的命名都是base.html)

2.在base.html中,通过块的语法定义未来子页面中会存在的块,注意块名一定要有意义

3.在子页面的第一行一定要先继承母版:{% extends 'base.html' %}

4.子页面的编辑:子页面中想要展示的内容要放到块的语法当中,例如:{% block page-main %}  ……html代码……{% endblock %},注意block(块)名要正确指定母版中的相应位置才行!!

6. 组件

 为了更好的体现代码的复用性,我们可以将所有html页面中常用的功能代码块提取出来,例如:导航条、页尾信息等固定的重复的代码单独的保存到单独的文件中,形成一个独立的功能模块,这就是组件。当我们在创建新的页面的时候,正好需要使用这些功能的时,就可以随时通过特定语法导入组件的文件就可以就可以了!!!

其实组件就是一个带有特定的固定的功能的html文件而已,‘组件’只是一个名词一个称呼而已!

导入组件的语法:

{% include 'nav.html' %}      // 假设  nav.html 是导航的代码,那通过这个导入语法,就可以把导航里面的代码引入到页面当中了

7. 静态文件相关

7.1 {% static %}

引用CSS文件时使用:

{% load static %}
<img src="{% static "mystyle.css" %}" />

引用JS文件时使用:

{% load static %}
<script src="{% static "mytest.js" %}"></script>

某个文件多处被用到可以存为一个变量(起别名

{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>
注意:static是Django内置的一个模块方法,因为,static可以从配置文件(setting.py)中的  STATIC_URL = '/static/'  和 STATICFILES_DIRS = []找到对应静态文件所在路径。
这样做有什么好处呢?例如:一个模板中引入一个css文件的方法为:
<link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css">

大家是不是以为上面这条引入css语句中的 “ static ” 直接是,项目文件中static文件呢?其实不是的!!!!!!

其实这个static是 STATIC_URL = '/static/' 中的static,而真实的路径是由 STATICFILES_DIRS = [] 里面的路径自动拼接而得到的!

7.2 {% get_static_prefix %}

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

get_static_prefix:是一个可以获取到 ' /static/ '字符串的函数,通过获取到的' /static/ '字符串手动拼接一条路径!

8. tag

8.1 simple_tag

和自定义filter类似,只不过接收参数的形式更加灵活


1.首先,跟自定义的filter一样,需要在“app01项目文件夹”创建一个存放simple_tag的py文件,可以命名为app01_mytag.py

2.第二,app01_mytag.py编辑,跟自定义的filter一样,需要引入template,如下:

  from django import template
  register = template.Library()

3.第三,app01_mytag.py编辑,注册register中simple_tag装饰器,如下:

    @register.simple_tag(name="myjoin")
    def myjoin(arg1, arg2, arg3):
    return "{} + {} + {}".format(arg1, arg2, arg3)

4.第四,模板文件使用自定义的simple_tag

    {% load app01_mytag %}        #先加载,存放自定义simple_tag的py文件模块
    {% myjoin "aa" "bb" "cc" %}     #正式使用装饰器,语法格式:{% 函数名或者注册的时候起的别名 参数1 参数2 参数3…… %}

5.结果,result >> aabbcc

8.2 inclusion_tag

更多的时候用于返回html代码片段,

注册的时候跟自定义filter和simple_tag的一样。

1.首先,需要在“app01项目文件夹”创建一个存放inclusion_tag的py文件,可以命名为app01_mytag_inclu.py。或者自定义的inclusion_tag函数和simple_tag一起放在同一文件

2.第二,app01_mytag_inclu.py编辑,同样需要引入template,如下:

  from django import template
  register = template.Library()

3.第三,app01_mytag_inclu.py编辑,同样是需要注册,但这里注册是的inclusion_tag,如下:

@register.inclusion_tag( 'result.html' )
def foo_result(n):
  n = 1 if n < 1 else int(n)
  data = ["第{}项".format(i) for i in range(1, n+1)]
  return {"data": data}

4.第四,需要将第三步的结果引入到result.html,进行字符串的替换之后,得到的html代码片段,才会返回给使用inclusion_tag的模板
result.html代码:

<ul>
{% for choice in data %}
  <li>{{ choice }}</li>
{% endfor %}
</ul>


5.第五,模板文件使用自定义的inclusion_tag

{% load app01_mytag_inclu %}    # 加载inclusion_tag所在的文件模块
{% foo_result 10 %}    # 使用装饰器,语法格式:{% 函数名 参数1 参数2 …… %}