13.模板

模板语言简称为DTL(Django Template Language)

13.1 模板语言

13.1.1 模板变量及解析顺序

模板变量名由数字,字母,下划线和点组成,不能以下划线开头使用模板变量:{{ 模板变量名 }}

解析顺序:

例如: {{ book.btitle }}

1)首先把 book 当成一个字典,把 btitle 当成键名,进行取值 book['btitle’]
2)把book当成一个对象,把 btitle当成属性,进行取值book.btitle
3)把book 当成一个对象,把 btitle 当成对象的方法,进行取值book.btitle

例如: {{ book.0 }}

1)首先把book当成一个字典,把0当成键名,进行取值book[0]
2)把book当成一个列表,把0当成下标,进行取值 book[0]

如果解析失败,则产生内容时用空字符串填充模板变量。

使用模板变量时,“. ”前面的可能是一个字典,可能是一个对象,也可能是一个列表。

·

13.1.2 模板标签

格式:{% 代码段 %}

for 循环:

{% for i in 列表 %}
     xxx   // 列表不为空时执行
{% empty %}
     xxx   // 列表为空时执行
{% endfor %}

可以通过{{ forloop.counter }}得到for循环遍历到了第几次。

if语句:

{% if条件 %}
{% elif条件 %}
{% else %}
{% endif %}

关系比较操作符:> , < , >= , == , !=
注:进行比较操作时,比较操作符两边必须有空格。

逻辑运算: not and or

代码实例:

book.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板标签</title>
    <style>
        .yellow {
            background-color: yellow;
        }
    </style>
</head>
<body>

{% for i in  books  %}
    {% if i.id <= 1 %}
        <li class="yellow">{{ i.btitle }}</li>
    {% endif %}
{% endfor %}
</body>
</html>

views.py

def books_play(request):
    book_all = Book.objects.all()
    return render(request, 'booktest/book.html', {'books': book_all})

实验结果:

ddt的应用 python python dto_转义

·

13.1.3 模板过滤器

过滤器用于对模板变量进行操作

过滤器本质是python函数

date:改变日期的显示格式

length:求长度。字符串,列表,元组,字典长度

default:设置模板变量的默认值

格式:模板变量 | 过滤器: 参数

·

代码实例:

books_display.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>显示图书信息</title>
</head>
<h3>图书信息:</h3>
<a href="/create">新增</a>
<body>
{% for book in books %}

        <li><a href="/books/{{ book.id }}">{{ book.btitle }}</a>---{{ book.bpub_date|date:'Y年-m月-d日' }} // 对日期的显示增加过滤器
            <a href="/delete/{{ book.id }}">删除</a></li>
{% endfor %}
<br/>
default过滤器:<br/>
{{ content|default:'默认值' }}
</body>
</html>

views.py

def books_display(request):
    books = BookInfo.objects.all()

    return render(request, 'booktest/books_display.html', {'books': books})

实验结果:

ddt的应用 python python dto_ddt的应用 python_02

·

自定义过滤器

1)首先,在app路径下创建 templatetags

2)在templatetags目录中创建自定义的python文件

3)导入包(from django.template import Library

4)创建LIbrary()对象

5)创建功能函数并进行装饰器装饰

6)在模板文件中加载自定义的python文件

7)增加过滤器

注:自定义的过滤器函数,至少有一个参数,最多两个参数

代码实例:
booktest/templatetags/filter_test.py

# 自定义过滤器
# 过滤器实质上是python函数

from django.template import Library

# 创建一个Library类的对象
register = Library()


@register.filter
def mod(num):
    '''判断num是否为偶数'''

    return num % 2 == 0


# 自定义的过滤器函数,至少有一个参数,最多两个
@register.filter()
def mod_val(num, val):
    '''判断num是否能被val整除'''

    return num % val == 0

books_display.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
{% load filter_test %}
<head>
    <meta charset="UTF-8">
    <title>显示图书信息</title>
</head>
<h3>图书信息:</h3>
<a href="/create">新增</a>
<body>
{% for book in books %}
        <li>{{ book.id }}--{{ book.id|mod }}---<a href="/books/{{ book.id }}">{{ book.btitle }}</a>
            ---{{ book.bpub_date|date:'Y年-m月-d日' }}--{{ book.id|mod_val:3 }}
            <a href="/delete/{{ book.id }}">删除</a></li>
{% endfor %}
<br/>
default过滤器:<br/>
{{ content|default:'默认值' }}
</body>
</html>

实验结果:

ddt的应用 python python dto_转义_03

·

13.1.4模板注释

单行注释

{# 注释内容 #}

多行注释:

{% comment %}
注释内容
{% endcomment %}

● 模板注释与html注释的区别

模板注释 通过浏览器检查网页源代码不会显示
html注释 通过浏览器检查网页源代码会显示出来

·

13.1.5 模板继承

在子模版中需要继承父模板时

{% extends '父模板路径' %}

● 子模版继承父模板后会继承父模板所有模板内容,并且无法直接增加内容,标题也和父模板一样

● 在父模板中增加预留块,在子模版中可通过对预留块的改写增加内容

● 在子模版的预留块中可通过 {{ block.super }} 继承父模板中该预留块的内容

● 对父模板的标题增加预留块,在子模版可以通过该预留块改写子模版的标题

ddt的应用 python python dto_ddt的应用 python_04

·

实例代码:

parentTemplate.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}父模板{% endblock title %}</title>
</head>
<body>
<h1>这是父模板</h1>

{% block b1 %}
    <h3>父模块b1信息</h3>
{% endblock b1 %}

{% block b2 %}
{% endblock b2 %}
</body>
</html>

subTemplate.html

{% extends 'booktest/parentTemplate.html' %}
{% block title %}子模版{% endblock title %}
{% block b1 %}

{{ block.super }}
<h3>这是子模块b1的内容</h3>

{% endblock b1 %}

{% block b2 %}
<h3>这是子模块b2的内容</h3>
{% endblock b2 %}

实验结果:

ddt的应用 python python dto_html_05

·

13.1.6 html转义

在模板上下文中的html标签默认是会被转义的

小于号 < 转换为 <
大于号 > 转换为 >
单引号 ‘ 转换为 '
双引号 " 转换为 "
与符号 & 转换为 &

要关闭模板上下文的转义,有两种方法:

过滤器

{{ 模板变量|safe }}

● 模板标签

{% autoescape off %}
模板语言代码
{% endautoescape %}

代码实例:

views.py

def escape_test(request):
    return render(request, 'booktest/escape_test.html', {'content': '<h1>hello</h1>'})

escape_test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>转义</title>
</head>
<body>
未进行转义时:<br/>
{{ content }}
<br/>
<br/>
用过滤器进行转义:
{{ content| safe }}
<br/>
用模板标签进行转义:
{% autoescape off %}
{{ content }}
{{ content }}
{% endautoescape %}
</body>
</html>

实验结果:

ddt的应用 python python dto_django_06

● 在模板硬编码中的字符串默认不会经过转义,如果需要转义,则需要手动进行转义

硬编码指的是在模板文件中固定死的静态代码

代码实例:

escape_test.html

模板硬编码中的字符串默认不会经过转义:<br/>
{{ tag|default:'<h1>hello</h1>' }}<br/>
<br/>
手动进行转义:<br/>
{{ tag|default:'<h1">>hello</h1>' }}
</body>
</html>

实验结果:

ddt的应用 python python dto_python_07

·

·

13.2 模板目录(templates)有两种创建路径:

1)在项目根目录中创建templates目录,该目录下存放模板文件

创建好后,在setting.py 文件中,配置一下模板文件的目录

ddt的应用 python python dto_转义_08

setting.py文件中有一个变量 BASE_DIR 表示这个项目的绝对路径,在本实验环境下为“/home/user/桌面/python/Django_test/test1

ddt的应用 python python dto_转义_09

则在模板路径中应该填入

os.path.join(BASE_DIR, ‘templates’) (路径相加需要用到os.path.join()方法)

ddt的应用 python python dto_html_10

2)在应用目录下创建templates目录,该目录下存放模板文件

在应用目录下创建后无需填写setting.py文件中的TEMPLATES的‘DIRS’,但必须让‘APP_DIRS'设置为True

注:当两种模板目录的存放方式都写了时,Django框架寻找模板文件时优先在项目根目录下寻找templates目录,如果没找到再去应用目录下寻找templates目录,当都没找到的话就会报出错误TemplateDoesNotExist at xxx/xxx
·

13.3 模板文件加载顺序

当服务器url正确时,服务器寻找相应的模板文件的顺序为下面红框中内容

ddt的应用 python python dto_转义_11

·

·

在templates目录下创建与应用同名的目录,比如这里我的应用名是booktest,我就在templates目录下创建一个booktest目录,在每个应用目录下存放属于该应用的模板文件

·

通过render方法调用模板文件,获取内容,进行模板渲染(将传入的值替换模板文件中相应的值),最后返回给浏览器

ddt的应用 python python dto_转义_12