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 初始化多维数组代码
Sep 06 Python
使用Python的Scrapy框架编写web爬虫的简单示例
Apr 17 Python
通过Python使用saltstack生成服务器资产清单
Mar 01 Python
Python登录并获取CSDN博客所有文章列表代码实例
Dec 28 Python
python监控文件并且发送告警邮件
Jun 21 Python
pytorch 更改预训练模型网络结构的方法
Aug 19 Python
python opencv实现图片缺陷检测(讲解直方图以及相关系数对比法)
Apr 07 Python
Python实现在线批量美颜功能过程解析
Jun 10 Python
python中什么是面向对象
Jun 11 Python
Python调用shell cmd方法代码示例解析
Jun 18 Python
Django vue前后端分离整合过程解析
Nov 20 Python
python 模块重载的五种方法
Apr 24 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中10个不常见却非常有用的函数
2010/03/21 PHP
PHP获取一段文本显示点阵宽度和高度的方法
2015/03/12 PHP
php设置页面超时时间解决方法
2015/09/22 PHP
PHP判断表达式中括号是否匹配的简单实例
2016/10/22 PHP
php die()与exit()的区别实例详解
2016/12/03 PHP
Yii2 加载css、js 载静态资源的方法
2017/03/10 PHP
动态样式类封装JS代码
2009/09/02 Javascript
javascript 解析url的search方法
2010/02/09 Javascript
yui3的AOP(面向切面编程)和OOP(面向对象编程)
2015/05/01 Javascript
js同源策略详解
2015/05/21 Javascript
js显示当前日期时间和星期几
2015/10/22 Javascript
js获取及判断键盘按键的方法
2015/12/01 Javascript
JS hashMap实例详解
2016/05/26 Javascript
JavaScript比较当前时间是否在指定时间段内的方法
2016/08/02 Javascript
微信小程序中button组件的边框设置的实例详解
2017/09/27 Javascript
修改node.js默认的npm安装目录实例
2018/05/15 Javascript
vue中使用vue-print.js实现多页打印
2020/03/05 Javascript
小程序实现简单语音聊天的示例代码
2020/07/24 Javascript
[02:51]DOTA2战队出征照拍摄花絮 TI3明星化身时尚男模
2013/07/22 DOTA
Python编程中使用Pillow来处理图像的基础教程
2015/11/20 Python
对numpy中的数组条件筛选功能详解
2018/07/02 Python
浅谈python连续赋值可能引发的错误
2018/11/10 Python
Django认证系统实现的web页面实现代码
2019/08/12 Python
python数据库操作mysql:pymysql、sqlalchemy常见用法详解
2020/03/30 Python
Python爬虫逆向分析某云音乐加密参数的实例分析
2020/12/04 Python
canvas小画板之平滑曲线的实现
2020/08/12 HTML / CSS
俄罗斯连接商品和买家的在线平台:goods.ru
2020/11/30 全球购物
程序员机试试题汇总
2012/03/07 面试题
JAVA中运算符的分类及举例
2015/09/12 面试题
UNIX文件系统分类
2014/11/11 面试题
办理居住证介绍信
2014/01/15 职场文书
企业宣传方案
2014/03/04 职场文书
慈善捐赠倡议书
2014/08/30 职场文书
2015年卫生院健康教育工作总结
2015/07/24 职场文书
2016大一新生军训心得体会
2016/01/11 职场文书
idea以任意顺序debug多线程程序的具体用法
2021/08/30 Java/Android