️️个人简介:以山河作礼。
️️:Python领域新星创作者,CSDN实力新星认证,阿里云社区专家博主,CSDN内容合伙人
:Web全栈开发专栏:《Web全栈开发》免费专栏,欢迎阅读!
:文章末尾扫描二维码可以加入粉丝交流群,不定期免费送书。
模板变量是指在模板中使用的变量,它们通常是从视图函数中传递过来的。
Django 模板语言的语法主要分为以下四个部分:
前面的内容中我们提到了模板变量,并且已经使用了它,如{{name}}。
Django模板引擎通过上下文处理器来完成字典提供的值(value)
与模板变量之间的替换,也就是用字典的 vaule来替换模板文件 xxxx.html 中的变量 {{name}},这就好比字典中 key 到
vaule 的映射。而我们无需关心内部细节是如何让实现的,这些由 Django 框架自己完成。
变量的命名规范
Django对于模板变量的命名规范没有太多的要求,可以使用任何字母、数字和下划线的组合来命名,且必须以字母或下划线开头,但是变量名称中不能有空格或者标点符号。
如何理解模板的变量语法,其实它有四种不同的使用场景,分别如下所示:
索引 index 查询
,如 {{变量名.index}},其中 index 为int类型即索引下标字典查询方法
,{{变量名.key}} 其中 key 代表字典的键,如 a[‘b’]属性或方法查询
,如 {{对象.方法}} ,把圆点前的内容理解成一个对象,把圆点后的内容理解为对象里面的属性或者方法函数调用
,如 {{函数名}}。下面我们对上面的语法依次进行说明,首先在views.py中添加如下代码:
def test_hello():
return '我是函数的返回数据'
class WebSite:
def web_name(self):
return 'Hello world!'
def test_html(request):
a = {'name': 'xxx',
'list_obj': ["Python", "C", "C++", "Java"],
'dict_obj': {'name': '百度', 'address': 'https://www.baidu.com/'},
'func': test_hello,
'class_obj': WebSite()} # 创建空字典,模板必须以字典的形式进行传参
return render(request, 'test_html.html', a)
其次在templates 目录下创建名为 test_html 的 html 文件,然后添加以下代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<p>名字是{{ name }}p>
<p>列表数据是{{ list_obj }}p>
<p>课程是{{ list_obj.0 }}p>
<p>变量dict_obj是{{ dict_obj }}p>
<p>dict_obj['address']是{{dict_obj.address}}p>
<p>函数fuction:{{ func }}p>
<p>类实例化对象:{{class_obj.web_name}}p>
body>
html>
然后在 urls.py 文件中添加路由配置,如下所示:
from django.contrib import admin
from django.urls import path
from Bookstore import views
urlpatterns = [
path('test_html/', views.test_html)
]
接下来访问指定的路由路径就可以访问到页面了。
在视图函数中必须将变量封装到字典中才允许传递到模板上,语法格式如下:
#方式1
def xxx_view(request)
dic = {
"变量1":"值1",
"变量2":"值2",
}
return render(request, 'xxx.html', dic)
#方式2
def xxx_view(request)
变量1=值1
变量2=值2
return render(request, 'xxx.html', locals())
注意:
locals() 返回当前函数作用域内全部局部变量形成的字典。
即将变量与值对应形成字典,并把这个字典作为 locals() 的返回值来使用。
Django 内置了许多标签用于简化模板的开发过程,同时 Django 也支持自定义标签,这极大的方便了 Web开发者,下面我们依次进行介绍。
Django 的模板系统对标签的解释是在渲染的过程中提供相应的逻辑,比如Python 语言中 if…else 语句、with 语句、以及 for 循环等,这些在 Django 的模板系统中都有对应的标签,不过稍微复杂些。
它们的使用方式如下所示:
{% tag %}
我们知道if 在 Python 语言中是判断条件是否成立的,在模板标签中它们作用是类似的,如果条件成立则显示块中的内容。
模板标签规定了 if 需要与 endif 成对出现 ,使用的方式如下所示:
{% if 条件表达式1 %}
......
{% elif 条件表达式2 %}
......
{% elif 条件表达式3 %}
......
{% else %}
......
{% endif %} # if的结束
上面的 if 示例中就是使用了开始标签和结束标签,它们分别写在了开始位置和结束位置。
注意:模板标签内部的两边空格不要省略。
那 if 标签具体又是如何使用的呢,下面我们通过一个简单的例子来看一下:
#在views.py 中添加如下代码
def test_if(request):
dic={'x':2**4}
return render(request,'test_if.html',dic)
在 templates 目录中创建 test_if.html 文件 ,并在body中添加以下代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
{% if x > 0 %}
<h2>{{ x }}是大于0的h2>
{% elif x == 0 %}
<h3>{{ x }}是等于0的h3>
{% elif x < 0 %}
<h4>{{ x }}是小于0的h4>
{% endif %}
body>
html>
最后在 urls.py 文件中配置路由如下所示:
path('test_if/',views.test_if)
从上面例子还可以看出,在 if 标签中可以使用算术操作符,如 >、<、==、<= 等符号,同时也可以使用逻辑运算符 and、or来连接多个条件,以及使用 not 对当前条件取反。
注意:elif 和 else 这两个标签是可选的,elif 标签可以不止一个,但是 else 标签只有一个,同时也可以都不出现在 if 标签中,只使用 if 与 endif。
如果当判断的条件太多时,为了避免过多的连接操作符的出现,同样可以考虑使用嵌套的 if 标签。
格式如下所示:
{% if 条件表达式1 %}
{% if 条件表达式2 %}
......
{% elif 条件表达式3 %}
......
{% else %}
......
{% endif %}
{% endif %}
在这里我们介绍另外一种方式来简单的演示如何使用嵌套 if 标签,在 views.py 文件中添加如下代码:
from django.template import Template, Context #调用template、以及上下文处理器方法
def Hello_MyWeb(request):
#调用template()方法生成模板
t = Template("""
{% if web.name == 'xx' %}
{% if printable %}
Hello xx
{% else %}
欢迎您下次访问,xx
{% endif %}
{% endif %}
""")
c = Context({'web': {'name': 'xx'}, 'printable': True}) #Context必须是字典类型的对象,用来给模板传递数据
html = t.render(c)
return HttpResponse(html)
然后我们在 urls.py 文件中为 hello_MyWeb() 函数配置路由映射关系,如下所示:
path('Hello_MyWeb/',views.Hello_MyWeb)
以上讲解了 Django 模板标签中的 if 标签的使用方法。在学习的过程一定要懂得融会贯通 ,因为 Django 是基于 Python 的Web 框架,它纵然有自己的特点,但是万变不离其宗,所以学会结合 Python 语言去学习会有利我们快速理解与掌握相关的知识。
for 标签用于对可迭代对象进行遍历,包括列表、元组等,它与 Python 中的 for 语法是类似的。for 标签 使用时也需要和 endfor 标签配合使用,当然它也有不同之处,那就是它多了一个可选的 empty 标签,比如用它来显示当列表不存在或者列表中元素为空的时候要显示的内容。
它的使用格式如下:
{% for 变量 in 可迭代对象 %}
... 循环语句
{% empty %}
... 可迭代对象无数据时填充的语句
{% endfor %}
我们通过一个具体的实例来看一下它的用法,在 views.py 中添加如下代码:
def test_for(request):
#调用template()方法生成模板
t1 = Template("""
{% for item in list %}
{{ item }}
{% empty %}
如果找不到你想要,可以来百度(网址:https://www.baidu.com)
{% endfor %}
""")
#调用 Context()方法
c1 = Context({'list': ['Python', 'Java', 'C', 'Javascript', 'C++']})
html = t1.render(c1)
return HttpResponse(html)
并配置路由映射关系,如下所示:
path('test_for/',views.test_for)
提示:与 Python 中的 for 循环不同的是,for 标签只能一次性地遍历完列表中的元素,不能中断(break),也不能跳过(continue)。
在 for 标签还提供了内置变量forloop,我们可以访问这个变量的属性从而获取 for 循环迭代过程中的一些信息,比如forloop.first,它的返回值是一个布尔值,当 for 循环迭代第一个元素的时候返回 True, 若有其余元素则返回的是False。
forloop 的属性主要有以下几个:
变量 | 描述 |
---|---|
forloop.counter | 用来计数,查看当前迭代第几个元素(从1开始索引) |
forloop.revcounter | 表示当前循环中剩余的未被迭代的元素数量(从1开始索引) |
forloop.first | 如果当前迭代的是第一个元素,则为True |
forloop.last | 如果当前迭代的是最后一个元素,则为True |
forloop.parentloop | 在嵌套循环中,用来引用外层循环的 forloop |
实例说明如下所示:
def test_forloop(request):
a = Template("""
{% for item in lists %}
{{ forloop.counter }}:{{ item }}
{% endfor %}
""")
b = Context({'lists': ['c语言', 'Django官网', 'Pytho官网']})
html = a.render(b)
return HttpResponse(html) # 数字与元素以 1:'c语言' 的形式出现
路由映射关系,如下所示:
path('test_forloop/', views.test_forloop),
下面是一些演示示例:
forloop.revcounter 表示当前循环中剩余的未被迭代的元素数量(从1开始索引)
{% for num in numbers %}
{{ num }} ({{ forloop.revcounter }} left)
{% endfor %}
假设 numbers 列表包含 [2, 4, 6, 8, 10]
,则渲染结果为:
2 (5 left)
4 (4 left)
6 (3 left)
8 (2 left)
10 (1 left)
forloop.first 如果当前迭代的是第一个元素,则为True
forloop.last 如果当前迭代的是最后一个元素
{% for i in list1 %}
{% if forloop.first %}
<p>通过forloop.first 获取到第一个参数{{ i }}p>
{% elif forloop.last %}
<p>通过forloop.last 获取到最后一个参数{{ i }}p>
{% else %}
<p>{{ i }} 的计数是 {{ forloop.counter }} ,后面未被迭代的数据为 {{ forloop.revcounter }} p>
{% endif %}
{% empty %}
<p>列表中没有数据p>
{% endfor %}
forloop.parentloop在嵌套循环中,用来引用外层循环的 forloop
{% for category in categories %}
<h2>{{ category.name }}h2>
{% if category.products %}
<ul>
{% for product in category.products %}
<li>{{ product.name }}li>
{% endfor %}
ul>
{% endif %}
{% endfor %}
假设 categories列表包含两个对象,每个对象包含一个名称属性和一个产品列表属性。渲染结果将输出每个类别的产品列表,最后还要输出类别的总数。
在内部循环中,我们可以使用
forloop.parentloop
引用外部循环上下文,在这里它允许我们检查是否在迭代列表内的最后一个元素,以便在所有类别都遍历完后输出总数。