Django框架模板用法详解


Posted in Python onJune 10, 2022

在上一章节中我们使用 django.http.HttpResponse() 来输出 "Hello World!"。该方式将数据与视图混合在一起,不符合 Django 的 MVC 思想。

本章节我们将为大家详细介绍 Django 模板的应用,模板是一个文本,用于分离文档的表现形式和内容。

一、模板应用实例

我们接着上一章节的项目将在 HelloWorld 目录底下创建 templates 目录并建立 runoob.html文件,整个目录结构如下:

HelloWorld/
|-- HelloWorld
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- settings.py
|   |-- settings.pyc
|   |-- urls.py
|   |-- urls.pyc
|   |-- views.py
|   |-- views.pyc
|   |-- wsgi.py
|   `-- wsgi.pyc
|-- manage.py
`-- templates
    `-- runoob.html

runoob.html 文件代码如下:

<h1>{{ hello }}</h1>

从模板中我们知道变量使用了双括号。

接下来我们需要向Django说明模板文件的路径,修改HelloWorld/settings.py,修改 TEMPLATES 中的 DIRS 为 [BASE_DIR+"/templates",],如下所示:

...TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR+"/templates",],       # 修改位置
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
...

我们现在修改 views.py,增加一个新的对象,用于向模板提交数据:

from django.shortcuts import render
 
def runoob(request):
    context          = {}
    context['hello'] = 'Hello World!'
    return render(request, 'runoob.html', context)

urls.py 文件代码:

from django.urls import path
 
from . import views
 
urlpatterns = [
    path('runoob/', views.runoob),
]

可以看到,我们这里使用 render 来替代之前使用的 HttpResponse。render 还使用了一个字典 context 作为参数。

context 字典中元素的键值 hello 对应了模板中的变量 {{ hello }}。

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

这样我们就完成了使用模板来输出数据,从而实现数据与视图分离。

接下来我们将具体介绍模板中常用的语法规则。

二、Django 模板标签

1、变量

模板语法:

view:{"HTML变量名" : "views变量名"}
HTML:{{变量名}}
from django.shortcuts import render

def runoob(request):
  views_name = "菜鸟教程"
  return  render(request,"runoob.html", {"name":views_name})

templates 中的 runoob.html :

<p>{{ name }}</p>

Django框架模板用法详解

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

2、列表

templates 中的 runoob.html中,可以用 . 索引下标取出对应的元素。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render

def runoob(request):
    views_list = ["菜鸟教程1","菜鸟教程2","菜鸟教程3"]
    return render(request, "runoob.html", {"views_list": views_list})

HelloWorld/templates/runoob.html 文件代码:

<p>{{ views_list }}</p>   # 取出整个列表
<p>{{ views_list.0 }}</p> # 取出列表的第一个元素

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

3、字典

templates 中的 runoob.html中,可以用 .键 取出对应的值。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render

def runoob(request):
    views_dict = {"name":"菜鸟教程"}
    return render(request, "runoob.html", {"views_dict": views_dict})

HelloWorld/templates/runoob.html 文件代码:

<p>{{ views_dict }}</p>
<p>{{ views_dict.name }}</p>

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

4、过滤器

模板语法:

{{ 变量名 | 过滤器:可选参数 }}

模板过滤器可以在变量被显示前修改它,过滤器使用管道字符,如下所示:

{{ name|lower }}

{{ name }} 变量被过滤器 lower 处理后,文档大写转换文本为小写。

过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入:

{{ my_list|first|upper }}

以上实例将第一个元素并将其转化为大写。

有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。 例如:

{{ bio|truncatewords:"30" }}

这个将显示变量 bio 的前30个词。

其他过滤器:

  • addslashes : 添加反斜杠到任何反斜杠、单引号或者双引号前面。
  • date : 按指定的格式字符串参数格式化 date 或者 datetime 对象,实例:
{{ pub_date|date:"F j, Y" }}
  • length : 返回变量的长度。

(1)default

default 为变量提供一个默认值。

如果 views 传的变量的布尔值是 false,则使用指定的默认值。

以下值为 false:

0  0.0  False  0j  ""  []  ()  set()  {}  None

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    name =0
return render(request, "runoob.html", {"name": name})

HelloWorld/templates/runoob.html 文件代码:

{{ name|default:"菜鸟教程666" }}

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

(2)length

返回对象的长度,适用于字符串和列表。

字典返回的是键值对的数量,集合返回的是去重后的长度。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render

def runoob(request):
    name ="菜鸟教程"
    return render(request, "runoob.html", {"name": name})

HelloWorld/templates/runoob.html 文件代码:

{{ name|length}}

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

(3)filesizeformat

以更易读的方式显示文件的大小(即'13 KB', '4.1 MB', '102 bytes'等)。

字典返回的是键值对的数量,集合返回的是去重后的长度。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render

def runoob(request):
    num=1024
    return render(request, "runoob.html", {"num": num})

HelloWorld/templates/runoob.html 文件代码:

{{ num|filesizeformat}}

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

(4)date

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

格式 Y-m-d H:i:s返回 年-月-日 小时:分钟:秒 的格式时间。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
import datetime
    now  =datetime.datetime.now()
return render(request, "runoob.html", {"time": now})

HelloWorld/templates/runoob.html 文件代码:

{{ time|date:"Y-m-d" }}

再次访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

(5)truncatechars

如果字符串包含的字符总个数多于指定的字符数量,那么会被截断掉后面的部分。

截断的字符串将以 ... 结尾。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    views_str = "菜鸟教程"
return render(request, "runoob.html", {"views_str": views_str})

HelloWorld/templates/runoob.html 文件代码:

{{ views_str|truncatechars:2}}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

(6)safe

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

要保证 views.py 传过来的数据绝对安全,才能用 safe。

和后端 views.py 的 mark_safe 效果相同。

Django 会自动对 views.py 传到HTML文件中的标签语法进行转义,令其语义失效。加 safe 过滤器是告诉 Django 该数据是安全的,不必对其进行转义,可以让该数据语义生效。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    views_str = "<a href='https://www.runoob.com/'>点击跳转</a>"
return render(request, "runoob.html", {"views_str": views_str})

HelloWorld/templates/runoob.html 文件代码:

{{ views_str|safe }}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

5、if/else 标签

基本语法格式如下:

{% if condition %}
     ... display
{% endif %}

或者:

{% if condition1 %}
   ... display 1
{% elif condition2 %}
   ... display 2
{% else %}
   ... display 3
{% endif %}

根据条件判断是否输出。if/else 支持嵌套。

{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not ),例如:

{% if athlete_list and coach_list %}
     athletes 和 coaches 变量都是可用的。
{% endif %}

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    views_num = 88
return render(request, "runoob.html", {"num": views_num})

HelloWorld/templates/runoob.html 文件代码:

{%if num > 90 and num <= 100 %}
优秀
{% elif num > 60 and num <= 90 %}
合格
{% else %}
一边玩去~
{% endif %}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

6、for 标签

{% for %} 允许我们在一个序列上迭代。

与 Python 的 for 语句的情形类似,循环语法是 for X in Y ,Y 是要迭代的序列而 X 是在每一个特定的循环中使用的变量名称。

每一次循环中,模板系统会渲染在 {% for %} 和 {% endfor %} 之间的所有内容。

例如,给定一个运动员列表 athlete_list 变量,我们可以使用下面的代码来显示这个列表:

<ul>
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
{% endfor %}
</ul>

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    views_list = ["菜鸟教程","菜鸟教程1","菜鸟教程2","菜鸟教程3",]
return render(request, "runoob.html", {"views_list": views_list})

HelloWorld/templates/runoob.html 文件代码:

{% for i in views_list %}
{{ i }}
{% endfor %}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

给标签增加一个 reversed 使得该列表被反向迭代:

{% for athlete in athlete_list reversed %}
...
{% endfor %}

HelloWorld/templates/runoob.html 文件代码:

{% for i in views_list  reversed%}
{{ i }}
{% endfor %}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

遍历字典: 可以直接用字典 .items 方法,用变量的解包分别获取键和值。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    views_dict = {"name":"菜鸟教程","age":18}
return render(request, "runoob.html", {"views_dict": views_dict})

HelloWorld/templates/runoob.html 文件代码:

{% for i,j in views_dict.items %}
{{ i }}---{{ j }}
{% endfor %}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

在 {% for %} 标签里可以通过 {{forloop}} 变量获取循环序号。

  • forloop.counter: 顺序获取循环序号,从 1 开始计算
  • forloop.counter0: 顺序获取循环序号,从 0 开始计算
  • forloop.revcounter: 倒叙获取循环序号,结尾序号为 1
  • forloop.revcounter0: 倒叙获取循环序号,结尾序号为 0
  • forloop.first(一般配合if标签使用): 第一条数据返回 True,其他数据返回 False
  • forloop.last(一般配合if标签使用): 最后一条数据返回 True,其他数据返回 False

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
     views_list = ["a", "b", "c", "d", "e"]
return render(request, "runoob.html", {"listvar": views_list})

HelloWorld/templates/runoob.html 文件代码:

{% for i in listvar %}
    {{ forloop.counter }}
    {{ forloop.counter0 }}
    {{ forloop.revcounter }}
    {{ forloop.revcounter0 }}
    {{ forloop.first }}
    {{ forloop.last }}
{% endfor %}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

{% empty %}

可选的 {% empty %} 从句:在循环为空的时候执行(即 in 后面的参数布尔值为 False )。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
  views_list = []
return render(request, "runoob.html", {"listvar": views_list})

HelloWorld/templates/runoob.html 文件代码:

{% for i in listvar %}
    {{ forloop.counter0 }}
{% empty %}
    空空如也~
{% endfor %}

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

可以嵌套使用 {% for %} 标签:

{% for athlete in athlete_list %}
    <h1>{{ athlete.name }}</h1>
    <ul>
    {% for sport in athlete.sports_played %}
        <li>{{ sport }}</li>
    {% endfor %}
    </ul>
{% endfor %}

7、ifequal/ifnotequal 标签

{% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。

下面的例子比较两个模板变量 user 和 currentuser :

{% ifequal user currentuser %}
    <h1>Welcome!</h1>
{% endifequal %}

和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签:8

{% ifequal section 'sitenews' %}
    <h1>Site News</h1>
{% else %}
    <h1>No News Here</h1>
{% endifequal %}

8、注释标签

Django 注释使用 {# #}。

{# 这是一个注释 #}

9、include 标签

{% include %} 标签允许在模板中包含其它的模板的内容。

下面这个例子都包含了 nav.html 模板:

{% include "nav.html" %}

三、csrf_token

csrf_token 用于form表单中,作用是跨站请求伪造保护。

如果不用{% csrf_token %}标签,在用 form 表单时,要再次跳转页面会报403权限错误。

用了{% csrf_token %}标签,在 form 表单提交数据时,才会成功。

解析:

首先,向浏览器发送请求,获取登录页面,此时中间件 csrf 会自动生成一个隐藏input标签,该标签里的 value 属性的值是一个随机的字符串,用户获取到登录页面的同时也获取到了这个隐藏的input标签。

然后,等用户需要用到form表单提交数据的时候,会携带这个 input 标签一起提交给中间件 csrf,原因是 form 表单提交数据时,会包括所有的 input 标签,中间件 csrf 接收到数据时,会判断,这个随机字符串是不是第一次它发给用户的那个,如果是,则数据提交成功,如果不是,则返回403权限错误。

四、自定义标签和过滤器

1、在 app 目录下创建 templatetags 目录(目录名只能是 templatetags)。

2、在 templatetags 目录下创建任意 py 文件,如:my_tags.py

3、在该 py 文件下:

from django import template

register = template.Library()   #register的名字是固定的,不可改变

4、利用装饰器 @register.filter 自定义过滤器。

注意:装饰器的参数最多只能有 2 个。

@register.filter
def my_filter(v1, v2):
    return v1 * v2

5、利用装饰器 @register.simple_tag 自定义标签。

@register.simple_tag
def my_tag1(v1, v2, v3):
    return v1 * v2 * v3

6、在使用自定义标签和过滤器前,要在 html 文件 body 的最上方中导入该 py 文件。

{% load my_tags %}

7、在 HTML 中使用自定义过滤器。

{{ 11|my_filter:22 }}

8、在 HTML 中使用自定义标签。

{% my_tag1 11 22 33 %}

9、语义化标签

在该 py 文件中导入 mark_safe。

from django.utils.safestring import mark_safe

定义标签时,用上 mark_safe 方法,令标签语义化,相当于 jQuery 中的 html() 方法。

和前端HTML文件中的过滤器 safe 效果一样。

@register.simple_tag
def my_html(v1, v2):
    temp_html = "<input type='text' id='%s' class='%s' />" %(v1, v2)
    return mark_safe(temp_html)

在HTML中使用该自定义标签,在页面中动态创建标签。

{% my_html "zzz" "xxx" %}

五、配置静态文件

1、在项目根目录下创建 statics 目录。

Django框架模板用法详解

2、在 settings 文件的最下方配置添加以下配置:

STATIC_URL = '/static/' # 别名 
STATICFILES_DIRS = [ 
    os.path.join(BASE_DIR, "statics"), 
]

Django框架模板用法详解

3、在 statics 目录下创建 css 目录,js 目录,images 目录,plugins 目录, 分别放 css文件,js文件,图片,插件。

4、把 bootstrap 框架放入插件目录 plugins。

5、在 HTML 文件的 head 标签中引入 bootstrap。

注意:此时引用路径中的要用配置文件中的别名 static,而不是目录 statics。

<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" rel="external nofollow" >

在模板中使用需要加入 {% load static %} 代码,以下实例我们从静态目录中引入图片。

HelloWorld/HelloWorld/views.py 文件代码:

from django.shortcuts import render
def runoob(request):
    name ="菜鸟教程"
return render(request, "runoob.html", {"name": name})

HelloWorld/templates/runoob.html 文件代码:

{% load static %}
{{name}}<img src="{% static "images/runoob-logo.png" %}" alt="runoob-logo">

再访问访问 http://127.0.0.1:8000/runoob,可以看到页面:

Django框架模板用法详解

六、模板继承

模板可以用继承的方式来实现复用,减少冗余内容。

网页的头部和尾部内容一般都是一致的,我们就可以通过模板继承来实现复用。

父模板用于放置可重复利用的内容,子模板继承父模板的内容,并放置自己的内容。

1、父模板

标签 block...endblock: 父模板中的预留区域,该区域留给子模板填充差异性的内容,不同预留区域名字不能相同。

{% block 名称 %} 
预留给子模板的区域,可以设置设置默认内容
{% endblock 名称 %}

2、子模板

子模板使用标签 extends 继承父模板:

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

子模板如果没有设置父模板预留区域的内容,则使用在父模板设置的默认内容,当然也可以都不设置,就为空。

子模板设置父模板预留区域的内容:

{ % block 名称 % }
内容 
{% endblock 名称 %}

接下来我们先创建之前项目的 templates 目录中添加 base.html 文件,代码如下:

HelloWorld/templates/base.html 文件代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
    <h1>Hello World!</h1>
    <p>菜鸟教程 Django 测试。</p>
    {% block mainbody %}
       <p>original</p>
    {% endblock %}
</body>
</html>

以上代码中,名为 mainbody 的 block 标签是可以被继承者们替换掉的部分。

所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。

runoob.html 中继承 base.html,并替换特定 block,runoob.html 修改后的代码如下:

HelloWorld/templates/runoob.html 文件代码:

{%extends "base.html" %}
 
{% block mainbody %}
<p>继承了 base.html 文件</p>
{% endblock %}

第一行代码说明 runoob.html 继承了 base.html 文件。可以看到,这里相同名字的 block 标签用以替换 base.html 的相应 block。

重新访问地址 http://127.0.0.1:8000/runoob,输出结果如下:

Django框架模板用法详解

到此这篇关于Django框架模板用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。


Tags in this post...

Python 相关文章推荐
Python获取Linux系统下的本机IP地址代码分享
Nov 07 Python
Python实现短网址ShortUrl的Hash运算实例讲解
Aug 10 Python
详解python基础之while循环及if判断
Aug 24 Python
Python测试人员需要掌握的知识
Feb 08 Python
selenium处理元素定位点击无效问题
Jun 12 Python
在python plt图表中文字大小调节的方法
Jul 08 Python
python多线程共享变量的使用和效率方法
Jul 16 Python
Python抓新型冠状病毒肺炎疫情数据并绘制全国疫情分布的代码实例
Feb 05 Python
Python3之外部文件调用Django程序操作model等文件实现方式
Apr 07 Python
python函数map()和partial()的知识点总结
May 26 Python
将pycharm配置为matlab或者spyder的用法说明
Jun 08 Python
call在Python中改进数列的实例讲解
Dec 09 Python
python库Tsmoothie模块数据平滑化异常点抓取
使用Django框架创建项目
Jun 10 #Python
Python实现信息管理系统
Jun 05 #Python
python实现学员管理系统(面向对象版)
Jun 05 #Python
python实现学生信息管理系统(面向对象)
Jun 05 #Python
Python使用pyecharts控件绘制图表
Jun 05 #Python
Python使用openpyxl模块处理Excel文件
Jun 05 #Python
You might like
php自定义函数实现JS的escape的方法示例
2016/07/07 PHP
漂亮的仿flash菜单,来自蓝色经典
2006/06/26 Javascript
用javascript实现的支持lrc歌词的播放器
2007/05/17 Javascript
javascript学习(二)javascript常见问题总结
2013/01/02 Javascript
js中的caller和callee属性介绍和例子
2014/06/07 Javascript
js实现图片从左往右渐变切换效果的方法
2015/02/06 Javascript
测试IE浏览器对JavaScript的AngularJS的兼容性
2015/06/19 Javascript
JavaScript实现图片拖曳效果
2017/09/08 Javascript
angular 服务的单例模式(依赖注入模式下)详解
2018/10/22 Javascript
vue-cli随机生成port源码的方法
2019/09/02 Javascript
JavaScript基于用户照片姓名生成海报
2020/05/29 Javascript
[07:08]2014DOTA2西雅图国际邀请赛 小组赛7月11日TOPPLAY
2014/07/11 DOTA
[50:34]VGJ.T vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
21行Python代码实现拼写检查器
2016/01/25 Python
Python3实现发送QQ邮件功能(html)
2017/12/15 Python
Python+OpenCV让电脑帮你玩微信跳一跳
2018/01/04 Python
一篇文章读懂Python赋值与拷贝
2018/04/19 Python
python二维列表一维列表的互相转换实例
2018/07/02 Python
python实现反转部分单向链表
2018/09/27 Python
python同步windows和linux文件
2019/08/29 Python
python动态文本进度条的实例代码
2020/01/22 Python
Python web框架(django,flask)实现mysql数据库读写分离的示例
2020/11/18 Python
Python 图片处理库exifread详解
2021/02/25 Python
深入理解css属性的选择对动画性能的影响
2016/04/20 HTML / CSS
html5指南-7.geolocation结合google maps开发一个小的应用
2013/01/07 HTML / CSS
美国药妆网站:EDCskincare.com(防晒、痤疮、抗衰老等)
2017/04/28 全球购物
英国家喻户晓的折扣商场:TK Maxx
2017/05/26 全球购物
计算机开发个人求职信范文
2013/09/26 职场文书
英文简历自荐信范文
2013/12/11 职场文书
绿化先进工作者事迹材料
2014/01/30 职场文书
《恐龙》教学反思
2014/04/27 职场文书
最美乡村医生事迹材料
2014/06/02 职场文书
2015年财务试用期工作总结
2014/12/24 职场文书
南阳市白酒市场的调查报告
2019/11/08 职场文书
php访问对象中的成员的实例方法
2021/11/17 PHP
Mysql多层子查询示例代码(收藏夹案例)
2022/03/31 MySQL