第五章 python Django 模版【模板标签 模板过滤器 模板继承 加载静态文件】

第五章 django模版

  • 第五章 django模版
    • 一、模版介绍
      • 1. DTL与普通的HTML文件的区别
      • 2. 渲染模板
    • 二、模板查找路径配置
    • 三、模版变量(DTL模版语法)
    • 四、常用模版标签
      • 1. if语句
      • 2. for...in... 标签
      • 3. for...in...empty 标签
      • 4. with 标签:在模版中定义变量
      • 5. url 标签
      • 6. overflow 标签
      • 7. spaceless 标签:移除html标签中空白字符
      • 8. autoescape 标签:开关自动转义功能
      • 9. verbatim 标签:不使用DTL解析引擎
    • 五、模版过滤器
      • 1. 为什么需要过滤器?
      • 2. add:将传进来的参数添加到原来的值上面
      • 3. cut:移除值中所有指定的字符串
      • 4. date:日期格式化成字符串
      • 5. default:提供默认值(布尔),值False
      • 6. default_if_none:值是 None
      • 7. first:返回第一个元素
      • 8. last:返回最后一个元素
      • 9. floatformat:四舍五入的方式格式化浮点类型
      • 10. join:字符拼接
      • 11. length:获取长度
      • 12. lower:所有字符转换成小写
      • 13. upper:所有字符转换成大写
      • 14. random:随机选择一个值
      • 15. safe:
      • 16. slice:切片
      • 17. stringtags:删除字符串html标签
      • 18. truncatechars:过滤器指定的长度
      • 19. truncatechars_html
    • 六、模版 继承
    • 七、加载静态文件

第五章 django模版

一、模版介绍

模板系统:DTL和Jinja2
DTL:Django Template Language

在之前的章节中,视图函数只是直接返回文本,而在实际生产环境中其实很少这样用,因为实际的页面大多是带有样式的HTML代码,这可以让浏览器渲染出非常漂亮的页面。
目前市面上有非常多的模板系统,其中最知名最好用的就是DTL和Jinja2。
DTL 是 Django Template Language 三个单词的缩写,也就是Django自带的模板语言。当然也可以配置Django支持Jinja2等其他模板引擎,但是作为Django内置的模板语言,和Django可以达到无缝衔接而不会产生一些不兼容的情况。
因此建议大家学习好DTL。

1. DTL与普通的HTML文件的区别

DTL模板是一种带有特殊语法的HTML文件,这个HTML文件可以被Django编译,可以传递参数进去,实现数据动态化。在编译完成后,生成一个普通的HTML文件,然后发送给客户端。

2. 渲染模板

渲染模板有多种方式。这里讲下两种常用的方式。

  1. render_to_string:找到模板,然后将模板编译后渲染成Python的字符串格式。最后再通
    HttpResponse 类包装成一个HttpResponse 对象返回回去。

示例代码如下:

from django.template.loader import render_to_string
from django.http import HttpResponse
def book_detail(request,book_id):
	html = render_to_string("detail.html")
	return HttpResponse(html)
  1. 以上方式虽然已经很方便了。但是django还提供了一个更加简便的方式,直接将模板渲染成字
    符串和包装成 HttpResponse 对象一步到位完成。

示例代码如下:

from django.shortcuts import render
	def book_list(request):
		return render(request,'list.html')

二、模板查找路径配置

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\1template_intro_deno1

在项目的 settings.py文件中。有一个TEMPLATES 配置,这个配置包含了模板引擎的配置,模板查找路径的配置,模板上下文的配置等。模板路径可以在两个地方配置。

1.DIRS:这是一个列表,在这个列表中可以存放所有的模板路径,以后在视图中使用 render或者 render_to_string 渲染模板的时候,会在这个列表的路径中查找模板。

2.APP_DIRS :默认为 True ,这个设置为 True 后,会在 INSTALLED_APPS 的安装了的 APP下的 templates文件加中查找模板。

3.查找顺序:比如代码render('list.html')。先会在 DIRS 这个列表中依次查找路径下有没有这个模板,如果有,就返回。

如果DIRS列表中所有的路径都没有找到,那么会先检查当前这个视图所处的app是否已经安装,如果已经安装了,那么就先在当前这个 app下的 templates 文件夹中查找模板,如果没有找到,那么会在其他已经安装了的app 中查找。

如果所有路径下都没有找到,那么会抛出一个TemplateDoesNotExist的异常。

三、模版变量(DTL模版语法)

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\2template_variable_demo

(1)在模版中使用变量,需要将变量放到{ {变量}}中。
(2)如果想要访问对象的属性,那么可以通过对象.属性名来进行访问。

示例代码如下:

class Person(object):
    def __init__(self, username):
        self.username = username

context = {
     
    'person': p
}

(3)如果想要访问一个字典的key对应的value,那么只能通过字典.key的方式进行访问,
不能通过中括号[]的形式进行访问。

示例代码如下:

context = {
     
    'person': {
     
        'username': 'zhiliao',
    }
}

那么以后在模版中访问username,就是以下代码person.username

(4)因为在访问字典的key时候也是使用来访问,因此不能在字典中定义字典本身就有的属性名当做key
否则字典的那个属性将变成字典中的key了。

示例代码如下:

context = {
     
    'person': {
     
        'username': 'zhiliao',
        'keys':'abc'  
    }
}

以上因为将key作为person这个字典的key了,因此以后在模版中访问person.keys的时候,返回的不是这个字典的所有key。

(5)如果想要访问列表或者元组,那么也是通过的方式进行访问,不能通过中括号[]的形式进行访问,
这一点和python中的是不一样的。

示例代码如下:

{
     {
      persons.1 }}

示例代码如下:

# profile.html模板代码
<p>{
     {
      username }}</p>

# views.py代码
def profile(request):
return render(request,'profile.html',context={
     'username':'huangyong'})

四、常用模版标签

if、for、with、url、overflow

1. if语句

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\3template_if_demo

  1. 所有的标签都是在{% %}
  2. if标签有闭合标签,就是{% endif %}
  3. if标签的判断运算符,就跟python中的判断运算符是一样的。
    ==、!=、<、<=、>、>=、in、not in、is、is not这些都可以使用。
  4. 还可以使用elif以及else等标签。

示例代码:

{
     % if "张三" in persons %}
	<p>张三</p>
{
     % else %}
	<p>李四</p>
{
     % endif %}

2. for…in… 标签

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\46template_for_damo1

1.for...in... 类似于Python中的 for...in...。可以遍历列表、元组、字符串、字典等一切可以遍历的对象。

示例代码1:for…in…


{
     % for person in persons %}
	<p>{
     {
      person.name }}</p>
{
     % endfor %}

2.如果想要反向遍历,那么在遍历的时候就加上一个 reversed

示例代码2:反向遍历-reversed

{
     % for person in persons reversed %}
	<p>{
     {
      person.name }}</p>
{
     % endfor %}

3.遍历字典的时候,需要使用 itemskeysvalues 等方法。在DTL 中,执行一个方法不能使用圆括号的形式。

示例代码3:遍历字典,items 、 keys 、 values

{
     % for key,value in person.items %}
	<p>key:{
     {
      key }}</p>
	<p>value:{
     {
      value }}</p>
{
     % endfor %}

4.在for循环中,DTL提供了一些变量可供使用。这些变量如下:
forloop.counter :当前循环的下标。以1作为起始值。
forloop.counter0 :当前循环的下标。以0作为起始值。
forloop.revcounter :当前循环的反向下标值。比如列表有5个元素,那么第一次遍历这个属性是等于5,第二次是4,以此类推。并且是以1作为最后一个元素的下标。
forloop.revcounter0 :类似于forloop.revcounter。不同的是最后一个元素的下标是从0
开始。

forloop.first :是否是第一次遍历。
forloop.last :是否是最后一次遍历。

示例代码4:DTL 变量,forloop.xxx

<td>{
     {
      forloop.revcounter }}</td>

3. for…in…empty 标签

这个标签使用跟 for...in...是一样的,只不过是在遍历的对象如果没有元素的情况下,会执行 empty'中的内容。

示例代码:没有元素

{
     % for person in persons %}
	<li>{
     {
      person }}</li>
{
     % empty %}
	暂时还没有任何人
{
     % endfor %}

4. with 标签:在模版中定义变量

有时候一个变量访问的时候比较复杂,那么可以先把这个复杂的变量缓存到一个变量上,以后就可以直接使用这个变量就可以了

示例代码如下:

context = {
     
	"persons": ["张三","李四"]
}

{
     % with lisi=persons.1 %}
	<p>{
     {
      lisi }}</p>
{
     % endwith %}

有几点需要强烈的注意:

  • with 语句中定义的变量,只能在{%with%}{%endwith%}中使用,不能在这个标签外面使用。

  • 定义变量的时候,不能在等号左右两边留有空格。比如{% with lisi = persons.1%}是错误的。

  • 还有另外一种写法同样也是支持的。

示例代码如下:

{
     % with persons.1 as lisi %}
<p>{
     {
      lisi }}</p>
{
     % endwith %}

5. url 标签

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\5template_url_demo

1.反转
url标签:在模版 中,我们经常要写一些url ,比如某个 a 标签中需要定义href 属性。当然如果通过硬编码的方式直接将这个 url写死在里面也是可以的。但是这样对于以后项目维护可能不是一件好事。因此建议使用这种反转的方式来实现,类似于 django 中的 reverse 一样。

示例代码1:

<a href="{% url 'book:list' %}">图书列表页面</a>

2.位置参数、关键字参数
如果 url 反转的时候需要传递参数,那么可以在后面传递。但是参数分位置参数和关键字参数。位置参数和关键字参数不能同时使用。

示例代码2:

# path部分
path('detail//',views.book_detail,name='detail')
# url反转,使用位置参数,`1`
<a href="{% url 'book:detail' 1 %}">图书详情页面</a>
# url反转,使用关键字参数,`book_id=1`
<a href="{% url 'book:detail' book_id=1 %}">图书详情页面</a>

3.查询字符串的参数
如果想要在使用 ‘url’ 标签反转的时候要传递查询字符串的参数,那么必须要手动在后面添加。?page=1

示例代码3:

<a href="{% url 'book:detail' book_id=1 %}?page=1">图书详情页面</a>

4.传递多个参数
如果需要传递多个参数,那么通过空格的方式进行分隔。

示例代码4:

<a href="{% url 'book:detail' book_id=1 page=2 %}">图书详情页面</a>

6. overflow 标签

overflow:hidden:将立标签浮动起来

示例代码:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .nav{
     
            overflow: hidden;
        }
    </style>
</head>
<body>
    <ul class="nav">
        <li>首页</li>
        <li>读书</li>
        <li>电影</li>
        <li>同城</li>
    </ul>
</body>

7. spaceless 标签:移除html标签中空白字符

1.移除html标签中的空白字符。包括空格、tab键、换行等

示例代码如下:

{
     % spaceless %}
<p>
<a href="foo/">Foo</a>
</p>
{
     % endspaceless %}

2.在渲染完成后,会变成以下的代码:

<p><a href="foo/">Foo</a></p>

3.spaceless 只会移除html标签之间的空白字符。而不会移除标签与文本之间的空白字符。

示例代码如下:

{
     % spaceless %}
<strong>
Hello
</strong>
{
     % endspaceless %}

这个将不会移除 strong 中的空白字符

8. autoescape 标签:开关自动转义功能

开启和关闭这个标签内元素的自动转义功能。自动转义是可以将一些特殊的字符。比如 < 转义成 html 语法能识别的字符,比如 < 会被转义成 < ,而 > 会被自动转义成 > 。模板中默认是已经开启了自动转义的。

示例代码如下:

# 传递的上下文信息
context = {
     
"info":"百度"
}

# 模板中关闭自动转义
{
     % autoescape on %}
{
     {
      info }}
{
     % endautoescape %}

那么就会显示百度的一个超链接。如果把 on 成 off ,那么就会显示成一个普通的字符串。

示例代码如下:

{
     % autoescape on %}
{
     {
      info }}
{
     % endautoescape %}

9. verbatim 标签:不使用DTL解析引擎

8.默认在 DTL 模板中是会去解析那些特殊字符的。比如 {% 和 %} 以
及 { { 等。如果你在某个代码片段中不想使用 DTL 的解析引擎。那么你可以把这个代码片段放在 verbatim 标签中。

示例代码下:

{
     % verbatim %}
{
     {
     if dying}}Still alive.{
     {
     /if}}
{
     % endverbatim %}

更多标签请参考官方文档:
https://docs.djangoproject.com/en/2.0/ref/templates/builtins/

五、模版过滤器

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\6template_filter_demo

1. 为什么需要过滤器?

因为在DTL中,不支持函数的调用形式'( )',因此不能给函数传递参数,这将有很大的局限性。而过滤器其实就是一个函数,可以对需要处理的参数进行处理,并且还可以额外接收一个参数(也就是说,最多只能有2个参数)。

2. add:将传进来的参数添加到原来的值上面

这个过滤器会尝试将参数 转换成整形然后进行相加。如果转换成整形过程中失败了,那么会将参数 进行拼接。如果是字符串,那么会拼接成字符串,如果是列表,那么会拼接成一个列表。示例代码如下:

{
     {
      value|add:"2" }}

如果 value 是等于4,那么结果将是6。如果 value 是等于一个普通的字符串,比如 abc ,那么结果将是 abc2 。 add 过滤器的源代码如下:

def add(value, arg):
	"""Add the arg to the value."""
	try:
		return int(value) + int(arg)
	except (ValueError, TypeError):
	try:
		return value + arg
	except Exception:
		return ''

3. cut:移除值中所有指定的字符串

类似于 python 中的 replace(args,"")

示例代码如下:

{
     {
      value|cut:" " }}

以上示例将会移除 value 中所有的空格字符。 cut 过滤器的源代码如下:

def cut(value, arg):
	"""Remove all values of arg from the given string."""
	safe = isinstance(value, SafeData)
	value = value.replace(arg, '')
	if safe and arg != ';':
		return mark_safe(value)
	return value

4. date:日期格式化成字符串

将一个日期按照指定的格式,格式化成字符串。

示例代码:

# 数据
context = {
     
 "birthday": datetime.now()
}
# 模版
{
     {
      birthday|date:"Y/m/d" }}

那么将会输出 2018/02/01 。其中 Y 代表的是四位数字的年份, m 代表的是两位数字的月
份, d 代表的是两位数字的日。
还有更多时间格式化的方式。见下表。

格式字符 描述 示例
Y 四位数字的年份 2018
m 两位数字的月份 01-12
n 月份,1-9前面没有0前缀 1-12
d 两位数字的天 01-31
j 天,但是1-9前面没有0前缀 1-31
g 小时,12小时格式的,1-9前面没有0前缀 1-12
h 小时,12小时格式的,1-9前面有0前缀 01-12
G 小时,24小时格式的,1-9前面没有0前缀 1-23
H 小时,24小时格式的,1-9前面有0前缀 01-23
i 分钟,1-9前面有0前缀 00-59
s 秒,1-9前面有0前缀 00-59

5. default:提供默认值(布尔),值False

如果值被评估为 False。比如 [] , “” , None , {} 等这些在 if 判断中为 False 的值,都会使用default过滤器提供的默认值。

示例代码如下:

{
     {
      value|default:"nothing" }}

如果 value是等于一个空的字符串。比如 “” ,那么以上代码将会输出nothing

6. default_if_none:值是 None

如果值是 None,那么将会使用 default_if_none 提供的默认值。这个和default 有区
别, default是所有被评估为 False 的都会使用默认值。而 default_if_none则只有这个值是等于 None的时候才会使用默认值。

示例代码如下:

7. first:返回第一个元素

返回列表/元组/字符串中的第一个元素

示例代码如下:

{
     {
      value|first }}

如果value 是等于 ['a','b','c'] ,那么输出将会是 a 。

8. last:返回最后一个元素

返回列表/元组/字符串中的最后一个元素。

示例代码如下:

{
     {
      value|last }}

如果 value是等于['a','b','c'],那么输出将会是 。

9. floatformat:四舍五入的方式格式化浮点类型

使用四舍五入的方式格式化一个浮点类型。如果这个过滤器没有传递任何参数。那么只会在小数点后保留一个小数,如果小数后面全是0,那么只会保留整数。当然也可以传递一个参数,标识具体要保留几个小数。

1.如果没有传递参数:

value 模版代码 输出
34.23234 { { value|floatformat }} 34.2
34.000 { { value|floatformat }} 34
34.260 { { value|floatformat }} 34.3

2.如果传递参数:

value 模版代码 输出
34.23234 { {value|floatformat:3}} 34.232
34.0000 { {value|floatformat:3}} 34.000
34.26000 { {value|floatformat:3}} 34.260

10. join:字符拼接

类似与Python 中的join,将列表/元组/字符串用指定的字符进行拼接。

示例代码如下:

{
     {
      value|join:"/" }}

如果value是等于['a','b','c'],那么以上代码将输出a/b/c

11. length:获取长度

获取一个列表/元组/字符串/字典的长度。

示例代码如下:

{
     {
      value|length }}

如果 value是等于['a','b','c'] ,那么以上代码将输出 3 。如果 valueNone ,那么以上将返回 0 。

12. lower:所有字符转换成小写

将值中所有的字符全部转换成小写。

示例代码如下:

{
     {
      value|lower }}

如果 value是等于 Hello World 。那么以上代码将输出hello world

13. upper:所有字符转换成大写

类似于lower,只不过是将指定的字符串全部转换成大写。

14. random:随机选择一个值

在被给的列表/字符串/元组中随机的选择一个值。

示例代码如下:

{
     {
      value|random }}

如果value是等于 ['a','b','c'],那么以上代码会在列表中随机选择一个。

15. safe:

标记一个字符串是安全的。也即会关掉这个字符串的自动转义。

示例代码如下:

{
     {
     value|safe}}

如果value是一个不包含任何特殊字符的字符串,比如这种,那么以上代码就会把字符串正常的输入。如果 value是一串html代码,那么以上代码将会把这个html 代码渲染到浏览器中。

16. slice:切片

类似于 Python中的切片操作。

示例代码如下:

{
     {
      some_list|slice:"2:" }}

以上代码将会给some_list 从 2 开始做切片操作。

17. stringtags:删除字符串html标签

删除字符串中所有的 html标签。

示例代码如下:

{
     {
      value|striptags }}

如果 value 是 hello world,那么以上代码将会输出 hello world

18. truncatechars:过滤器指定的长度

如果给定的字符串长度超过了过滤器指定的长度。那么就会进行切割,并且会拼接三个点来作为省略号。

示例代码如下:

{
     {
      value|truncatechars:5 }}

如果value是等于北京欢迎您~ ,那么输出的结果是 北京...。可能你会想,为什么不会 北京欢迎您… 呢。因为三个点也占了三个字符,所以 北京 +三个点的字符长度就是5。

19. truncatechars_html

类似于 truncatechars ,只不过是不会切割 html 标签。

示例代码如下:

{
     {
      value|truncatechars:5 }}

如果 value 是等于

北京欢迎您~

,那么输出将是

北京...

六、模版 继承

文件地址:
E:\Python3.8.0 \python_item\python_diango\chapter03\7template_inherit_demo

在前端页面开发中。有些代码是需要重复使用的。这种情况可以使用 include标签来实现。也可以使用另外一个比较强大的方式来实现,那就是模版继承。模版继承类似于Python 中的类,在父类中可以先定义好一些变量和方法,然后在子类中实现。模版继承也可以在父模版中先定义好一些子模版需要用到的代码,然后子模版直接继承就可以了。并且因为子模版肯定有自己的不同代码, 因此可以在父模版中定义一个block接口,然后子模版再去实现。

以下是父模版的代码:

{
     % load static %}
<!DOCTYPE html>
<html lang="en">
<head>
	<link rel="stylesheet" href="{% static 'style.css' %}" />
	<title>{
     % block title %}我的站点{
     % endblock %}</title>
</head>

<body>
	<div id="sidebar">
		{
     % block sidebar %}
			<ul>
				<li><a href="/">首页</a></li>
				<li><a href="/blog/">博客</a></li>
			</ul>
		{
     % endblock %}
	</div>
	<div id="content">
		{
     % block content %}{
     % endblock %}
	</div>
</body>
</html>

这个模版,我们取名叫做 base.html ,定义好一个简单的 html骨架,然后定义好两个 block接口,让子模版来根据具体需求来实现。子模板然后通过extends标签来实现,

示例代码如下:

{
     % extends "base.html" %}

{
     % block title %}博客列表{
     % endblock %}

{
     % block content %}
	{
     % for entry in blog_entries %}
		<h2>{
     {
      entry.title }}</h2>
		<p>{
     {
      entry.body }}</p>
	{
     % endfor %}
{
     % endblock %}

需要注意的是:
extends标签必须放在模版的第一行。
子模板中的代码必须放在block中,否则将不会被渲染。

如果在某个 block 中需要使用父模版的内容,那么可以使用 { {block.super}}来继承。比如上例, {%block title%} ,如果想要使用父模版的 title ,那么可以在子模版的 title block 中使用{ { block.super }} 来实现。

在定义block的时候,除了在block 开始的地方定义这个 block 的名字,还可以在 block结束的时候定义名字。比如 {% block title %}{% endblock title %}。这在大型模版中显得尤其有用,能让你快速的看到 block 包含在哪里。

七、加载静态文件

文件地址:
E:\Python3.8.0\python_item\python_diango\chapter03\8template_static_demo

在一个网页中,不仅仅只有一个 html 骨架,还需要 css 样式文件, js 执行文件以及一些图片等。
因此在 DTL 中加载静态文件是一个必须要解决的问题。在 DTL 中,使用 static 标签来加载静态文件。要使用 static 标签,首先需要 {% load static %}

加载静态文件的步骤如下:

  1. 首先确保 django.contrib.staticfiles 已经添加到 settings.INSTALLED_APPS 中。

  2. 确保在 settings.py中设置了 STATIC_URL

  3. 在已经安装了的 app 下创建一个文件夹叫做static·,然后再在这个 static文件夹下创建一个当前app的名字的文件夹,再把静态文件放到这个文件夹下。例如你的 app 叫做book ,有一个静态文件叫做 zhiliao.jpg,那么路径为 book/static/book/zhiliao.jpg

    (为什么在 app 下创建一个 static 文件夹,还需要在这个static 下创建一个同 app名字的文件夹呢?
    原因是如果直接把静态文件放在 static文件夹下,那么在模版加载静态文件的时候就是使用zhiliao.jpg,如果在多个app之间有同名的静态文件,这时候可能就会产生混淆。而在 static文件夹下加了一个同名app文件夹,在模版中加载的时候就是使用app/zhiliao.jpg ,这样就可以避免产生混淆。)

  4. 如果有一些静态文件是不和任何 app挂钩的。那么可以在settings.py中添加 STATICFILES_DIRS ,以后 DTL 就会在这个列表的路径中查找静态文件。
    比如可以设置为:

    STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static")
    	 ]
    
  5. 在模版中使用 load标签加载 static标签。比如要加载在项目的 static 文件夹下的style.css的文件。

那么示例代码如下:

 {
     % load static %}
<link rel="stylesheet" href="{% static 'style.css' %}">
  1. 如果不想每次在模版中加载静态文件都使用 load加载static标签,那么可以在settings.py 中的TEMPLATES/OPTIONS 添加builtins:['django.templatetags.static'],这样以后在模版中就可以直接使用 static 标签,而不用手动的load了。

  2. 如果没有在settings.INSTALLED_APPS中添加django.contrib.staticfiles 。那么我们就需要
    手动的将请求静态文件的url与静态文件的路径进行映射了。

示例代码如下:

from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
 # 其他的url映射
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

你可能感兴趣的:(django,django)