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 matlibplot绘制多条曲线图
Feb 19 Python
Python中安装easy_install的方法
Nov 18 Python
在python中利用GDAL对tif文件进行读写的方法
Nov 29 Python
python函数与方法的区别总结
Jun 23 Python
pandas实现to_sql将DataFrame保存到数据库中
Jul 03 Python
PyQtGraph在pyqt中的应用及安装过程
Aug 04 Python
django rest framework serializer返回时间自动格式化方法
Mar 31 Python
Python基于进程池实现多进程过程解析
Apr 30 Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
Jul 14 Python
python 实现图片修复(可用于去水印)
Nov 19 Python
pytorch 计算Parameter和FLOP的操作
Mar 04 Python
自动在Windows中运行Python脚本并定时触发功能实现
Sep 04 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的PSR规范中文版
2013/09/28 PHP
全面解读PHP的Yii框架中的日志功能
2016/03/17 PHP
php实现的二分查找算法示例
2017/06/20 PHP
jQuery 版本的文本输入框检查器Input Check
2009/07/09 Javascript
jquery easyui的tabs使用时的问题
2010/03/23 Javascript
使用JQuery和CSS模拟超链接的用户单击事件的实现代码
2012/05/23 Javascript
jquery固定底网站底部菜单效果
2013/08/13 Javascript
jquery next nextAll nextUntil siblings的区别介绍
2013/10/05 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
将HTML格式的String转化为HTMLElement的实现方法
2014/08/07 Javascript
推荐 21 款优秀的高性能 Node.js 开发框架
2014/08/18 Javascript
JavaScript 基础表单验证示例(纯Js实现)
2017/07/20 Javascript
nodejs的路径问题的解决
2018/06/30 NodeJs
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
webpack多入口多出口的实现方法
2018/08/17 Javascript
Nodejs技巧之Exceljs表格操作用法示例
2019/11/06 NodeJs
JavaScript判断数据类型有几种方法及区别介绍
2020/09/02 Javascript
vue-cli3 热更新配置操作
2020/09/18 Javascript
Openlayers实现测量功能
2020/09/25 Javascript
[51:14]LGD vs VP 2018国际邀请赛淘汰赛BO3 第一场 8.21
2018/08/22 DOTA
python中global用法实例分析
2015/04/30 Python
Django中的“惰性翻译”方法的相关使用
2015/07/27 Python
多个应用共存的Django配置方法
2018/05/30 Python
Python考拉兹猜想输出序列代码实践
2019/07/05 Python
使用 python pyautogui实现鼠标键盘控制功能
2019/08/04 Python
css3 pointer-events 介绍详解
2017/09/18 HTML / CSS
Charlotte Tilbury英国官网:英国彩妆品牌
2017/05/26 全球购物
.NET初级开发工程师面试题
2014/04/18 面试题
介绍一下write命令
2012/09/24 面试题
民族团结先进个人材料
2014/02/05 职场文书
2014年幼儿园元旦活动方案
2014/02/13 职场文书
公证书标准格式
2014/04/10 职场文书
捐书活动总结
2014/05/04 职场文书
服务行业口号
2014/06/11 职场文书
中学生2014国庆节演讲稿:不屈的民族
2014/09/21 职场文书
初中毕业生感言
2015/07/31 职场文书