深入模板

本文最后更新于:2 年前

关于模板

Django 的模板文件是一个文本文件,这个文件可以是任何类型的文本(如HTML、CSV等),但通常保存为HTML类型。

模板的作用:将业务逻辑(View)和显示内容( Template)分离。

模板的使用步骤

  1. 准备静态 HTM L页面,放到目录 templates 下;
  2. 在 settings.py 配置 TEMPLATE_DIRS,指定模版加载路径;
  3. 编写视图文件 view.py 中 render() 函数内容;
  4. 通过模板标签修改 HTML 页面显示内容。

在不使用模板的情况下输出指定内容:

1
2
3
4
5
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("<h1>Hello World</h1>")

使用模板的情况下输出指定内容:

  1. 创建hello.html作为模板,放到项目的 templates 下;

  2. 在 settings.py 配置 TEMPLATE_DIRS,指定模版加载路径;

  3. 编写视图文件 view.py 中 render() 函数内容;

    image-20220405231841457

  4. 通过模板标签修改 HTML 页面显示内容。

配置路由运行项目测试:

TEMPLATES 选项配置详解

在配置模板引擎时通常需要为其指定四项信息:BACKENDDIRSAPP_DIRSOPTIONS

常用OPTIONS配置项

模板文件的位置

在实际项目中,为区分不同应用的 html 文件,我们一般会在项目的 template 目录下分别以应用名创建子文件夹,此时只需在 render() 方法中加上子文件夹名即可。templates/blog/bloglist.html,在 render() 中声明为: render(request, 'blog/bloglist.html', {"blogs": blogs}) 。 (这种方法需要在 settings.py 配置 TEMPLATE_DIRS,指定模版加载路径。)

有时存放模板文件我们也会采用另一种方式,就是在每个 app 应用下分别创建 templates 文件夹。此时无需配置 TEMPLATES 中参数,因为 APP_DIRS 配置项默认为 True,会自动从已安装应用程序的目录中寻找 html 模板文件。

模板语言

注释

  • 单行注释

    1
    {# 单行注释内容 #}
  • 多行注释

    1
    2
    3
    {%comment%}
    多行注释内容
    {%comment%}

模板变量

模板变量用于标识模板中会动态变化的数据,当模板被渲染时,模板引擎将其替换为视图中传递而来的真实数据。(动态取值)

  • 模板变量名由字母、数字和下画线(“_”)组成,但不能以下画线开头。

  • {{ }} 中的变量可以是一个普通的变量,也可以是某个对象或属性。

1
2
{# name为字符串类型,如name=’张三’ #}
{{ name }}
1
2
3
{# 如obj={“name”:”张三”,”age”:18 #}
{{obj.name}}
{{obj.age}}

标签

标签蕴含一定的逻辑,它的功能要比变量复杂,例如一些标签用于输出文本;一些标签通过执行循环或逻辑控制流;一些标签加载外部信息到模板中,以供后续变量的使用。

标签格式简单,例如:{% tag %};也有一些标签必须成对出现,以标识模板文本的开始和结束,示例格式如下:

1
2
3
{% tag %}
...
{% endtag %}

常用标签

if 标签

if/elif/else 是条件判断标签,与 Python 中的 if、elif、else 含义相同,若条件为 True,显示相应子句中的内容。

if 标签允许使用逻辑运算符:and、or 或 not 进行布尔测试,允许同一标签中同时使用 and 和 or,and的优先级高于 or。

需要注意的是,模板语言的if标签不支持括号,若需明确表示混合语句中子句的优先级,应使用 if 嵌套语句。

for 标签

模板语言中 for 的用法与 Python 中的 for 相同。使用 for 标签遍历列表 ulist,并输出所有元素,示例代码如下:

Django为for循环定义了一些变量,具体如下表所示:

示例代码如下:

include 标签

在模板中包含(引入)其他模板中的内容与变量。

extend 标签

  • extends 标签标记当前模板所继承的模板。

  • **定义可由子模板覆盖的块: {% block 标记名%} ... {% endblock %}**。

extends 标签与 include 标签的区别是:extends 标签可以对继承过来的模板做补充和修改,功能更强大

csrf_token 标签

{% csrf_token %} 标签是一种防止跨站攻击的方法,一般是在制作表单提交页面时使用 {% csrf_token %} 标签。

跨站请求伪造(Cross Site Request Forgery,CSRF)是伪造客户端请求的一种攻击,即携带访问网站 A 时的 Cookie 访问网站 B,达到伪造请求的效果。

对于django中设置防跨站请求伪造功能有分为全局和局部

  • 全局

    django 已经为用户实现了防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。此项在创建项目时,默认被启用。

  • 局部

    • @csrf_protect:为当前函数强制设置防跨站请求伪造功能,即便 settings 中没有设置全局中间件。

    • @csrf_exempt:取消当前函数防跨站请求伪造功能,即便 settings 中设置了全局中间件。

过滤器

语法格式

过滤器主要是对模板变量的内容进行处理,如进行替换、大小写转换等操作,其语法格式如下:

1
{{ variables|filters }}

使用多个管道符号(“|”)连接多个过滤器,连续对同一变量进行过滤,其语法格式如下:

1
{{ variables|filters1|filters2... }}

需要注意的是,管道符号和变量、过滤器之间不能有空格。

一些过滤器可以接收参数,过滤器与参数之间使用 “:” 分隔。若参数中含有空格,参数必须放在引号之内,例如 {{ list|join:", " }}

内置过滤器

过滤器 说明 使用形式
upper 以大写方式输出 {{ variables|upper}}
add 给变量添加数值 {{ variables|add:"5"}}
capfirst 将首字母转换为大写 {{ "good"|capfirst}},返回 “Good”
lower 将字符串转换为小写 {{ variables|lower}}
cut 删除指定字符串 {{ "Zhang San"|cut:"San"}}
date 将日期数据按给定的格式输出 {{ variables|date:"D d M Y"}}
length 返回变量的长度 {{ variables|length}}
first 返回列表中的第一个item {{ variables|first}}
last 返回列表中的最后一个item {{ variables|last}}
safe 关闭html转义 {{ variables|safe}}

自定义过滤器

Django 除提供丰富的内置过滤器外,还可以自定义过滤器。自定义的过滤器和标签通常位于应用目录中的包 templatetags 之下,你可以在 templatetags 包中创建文件,在文件中自定义过滤器和标签。

需要注意的是,这个文件将被 load 标签加载到模板中,应避免文件名与其他应用的标签和过滤器重名。


  1. 为应用 users 添加自定义过滤器,假设过滤器位于文件 myfilter.py 中,此时该应用的目录结构如下:

  2. myfilter.py文件代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from django import template

    #声明一个模板对象,也称为注册过滤器
    register = template.Library()

    #声明并定义过滤器
    @register.filter
    def myreplace(value, arg):
    # 把传递过来的参数arg替换为'~'
    return value.replace(arg, '~')
  3. 将定义好的过滤器注册到 INSTALL_APPS 中:

  4. 创建模板,在 templates/index.html 中使用前面自定义过滤器,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {% load myfilter %}
    <!DOCTYPE html>
    <html>
    ... ...
    <body>
    <h1>
    {{ '在这里使用我自定义的过滤器!!!' | myreplace:'!'}}
    </h1>
    </body>
    </html>