Django框架基础3
本节主要分为两个内容:
- Django模板加载与响应
- 模板精讲(模板变量、模板标签、判断逻辑(if和for))
一、Django模板加载与响应
Django 的模板系统将 Python 代码与 HTML 代码解耦,动态地生成 HTML 页面。Django 项目可以配置一个或多个模板引擎,但是通常使用 Django 的模板系统时,应该首先考虑其内置的后端 DTL(Django Template Language)Django 模板语言。
1、什么是模板
在 Django 中,模板是可以根据字典数据动态变化的,并且能够根据视图中传递的字典数据动态生成相应的 HTML 网页。Django 中使用 Template 来表示模板,Template 对象定义在 django/template/base.py 文件中,它的构造函数如下所示:
def __init__(self,template_string,origin=None,name=None,engine=None)
-
模板的配置
首先按照
BookStore/templates
路径创建模板文件夹 templates,在 settings.py 配置文件中有一个 TEMPLATES 变量,如下所示:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], #指定模板文件的存放路径
'APP_DIRS': True, #搜索APP里面的所有templates目录
'OPTIONS': {
'context_processors': [ #context_processors 用于配置模板上下文处理器
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
-
-
BACKEND : Django默认设置,指定了要是用的模板引擎的 Python 路径;
-
DIRS : 一个目录列表,指定模板文件的存放路径,可以是一个或者多个。模板引擎将按照列表中定义的顺序查找模板文件;
-
APP_DIRS : 一个布尔值,默认为 Ture。表示会在安装应用中的 templates 目录中搜索所有模板文件;
-
OPTIONS : 指定额外的选项,不同的模板引擎有着不同的可选参数,例如 context_processors 用于配置模板上下文处理器,在使 RequestContext 时将看到它们的作用。
-
-
修改settings配置文件
'DIRS': [os.path.join(BASE_DIR, 'templates')]
2、模板的加载与响应方式
-
方法一:通过 loader 获取模板,通过 HttpResponse 进行响应
from django.http import HttpResponse
from django.template import loader
# 1.通过loader加载模板
t = loader.get_template("模板文件名")
# 2.将t转换成HTML字符串
html = t.render(字典数据)
# 3.用响应对象将转换的字符串内容返回给浏览器
return HttpResponse(html)
- 方法二:使用 render 方法直接加载并响应模板
from django.shortcuts import render
return render(request,'模板文件名', 字典数据)
下面我们对上述两种方式分别来说明:
#方式一
from django.http import HttpResponse
from django.template import loader # 导入loader方法
from django.shortcuts import render #导入render 方法
def test_html(request):
t=loader.get_template('test.html')
html=t.render({'name':'乔治老师真厉害'}) #以字典形式传递数据并生成html
return HttpResponse(html) # 以 HttpResponse方式响应html
#方式二
from django.shortcuts import render #导入reder方法
def test_html(request):
return render(request,'test.html',{'name':'乔治老师真厉害'}) #根据字典数据生成动态模板
templates 目录下创建 test.html 文件并在其中添加如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p style="font-size:50px;color:green">
{{name}}
</p>
</body>
</html>
提示:{{name}} 属于django模板语言的语法,代表一个变量,在后续章节我们会讲解。
如下所示:
from django.contrib import admin
from django.urls import path
from Bookstore import views # 这句代码自己加
urlpatterns = [
path('admin/', admin.site.urls),
path('test/', views.test_html)
]
最后在urls.py文件同级目录创建一个views.py文件,添加如下代码:
# 方式一
from django.template import loader # 导入loader方法
from django.shortcuts import render # 导入render 方法
from django.http import HttpResponse
def test_html(request):
t = loader.get_template('test.html')
html = t.render({'name': '乔治老师真厉害'}) # 以字典形式传递数据并生成html
return HttpResponse(html) # 以 HttpResponse方式响应html
从上述过程我们不难体会 Django 视图函数的实现流程。
然后我们配置了视图函数的路由映射关系;最后定义了视图函数 test_html()。
3、render方法详解
render 方法的作用是结合一个给定的模板和一个给定的字典,并返回一个渲染后的 HttpResponse 对象。通俗的讲就是把字典格式的内容,加载进 templates 目录中定义的 HTML 文件,最终通过浏览器渲染呈现。
render(request, template_name, context=None, content_type=None, status=None, using=None)
-
request:是一个固定参数,用于生成响应的请求对象
-
template_name: templates 中定义的文件, 要注意路径名。比如 "templates\appname\index.html", 参数就要写"appname\index.html"
-
context: 要传入文件中用于渲染呈现的数据, 默认是字典格式;
-
content_type: 生成的文档要使用的媒体格式类型。默认为 DEFAULT_CONTENT_TYPE 设置的值;
-
status: http 的响应代码,默认是 200;
-
using: 用于加载模板使用的模板引擎的名称。
二、模板精讲
上节我们详细讲述了模板与视图函数如何进行配合使用,同时我们介绍了加载与响应模板的两种方式。
我们知道,模板是文本文件,比如我们常见的有 HTML、CSV、TXT 等。
Django 模板语言的语法主要分为以下四个部分:
-
变量
-
标签
-
过滤器
-
注释
1、模板变量
Django模板引擎通过 context_processors 这个上下文处理器来完成字典提供的值(value)与模板变量之间的替换,也就是用字典的 vaule“乔治老师真厉害”来替换模板文件 test.html 中的变量 {{name}},这就好比字典中 key 到 vaule 的映射。而我们无需关心内部细节是如何让实现的,这些由 Django 框架自己完成。
-
变量的命名规范
Django 对于模板变量的命名规范没有太多的要求,可以使用任何字母、数字和下划线的组合来命名,且必须以字母或下划线开头,但是变量名称中不能有空格或者标点符号。
-
模板变量的语法
如何理解模板的变量语法呢?其实它有四种不同的使用场景,分别如下所示:
-
索引 index 查询,如 {{变量名.index}},其中 index 为int类型即索引下标
-
字典查询方法,{{变量名.key}} 其中 key 代表字典的键,如 a['b']
-
属性或方法查询,如 {{对象.方法}} ,把圆点前的内容理解成一个对象,把圆点后的内容理解为对象里面的属性或者方法
-
函数调用,如 {{函数名}}。
下面我们对上面的语法依次进行说明,首先在views.py中添加如下代码:
-
def test_html(request):
a = {} # 创建空字典,模板必须以字典的形式进行传参
a['name'] = '乔治'
a['course'] = ["Python", "C", "C++", "Java"]
a['b'] = {'name': '享学', 'address': 'https://www.baidu.com/'}
a['test_hello'] = test_hello
a['class_obj'] = Website()
return render(request, 'test_html.html', a)
def test_hello():
return '欢迎来到乔治老师django课堂'
class Website:
def Web_name(self):
return 'Hello world!'
其次在templates 目录下创建名为 test_html 的 html 文件,然后添加以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>网站的名字是{{ name }}</p>
<p>课程包含{{ course.0 }}</p>
<p>变量a是{{ b }}</p>
<p>a['address']是{{b.address}}</p>
<p>函数fuction:{{ test_hello }}</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('admin/', admin.site.urls),
path('test/', views.test_html),
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() 返回当前函数作用域内全部局部变量形成的字典。
2、模板标签
Django 内置了许多标签用于简化模板的开发过程,同时 Django 也支持自定义标签,这极大的方便了 Web 开发者,下面我们依次进行介绍。
Django 的模板系统对标签的解释是在渲染的过程中提供相应的逻辑,比如Python 语言中 if...else 语句、with 语句、以及 for 循环等,这些在 Django 的模板系统中都有对应的标签,不过稍微复杂些。
它们的使用方式如下所示:
{% tag %}
(1)判断逻辑的if标签
我们知道if 在 Python 语言中是判断条件是否成立的,在模板标签中它们作用是类似的,如果条件成立则显示块中的内容。模板标签规定了 if 需要与 endif 成对出现 ,使用的方式如下所示:
{% if 条件表达式1 %}
......
{% elif 条件表达式2 %}
......
{% elif 条件表达式3 %}
......
{% else %}
......
{% endif %}
注意:模板标签内部的两边空格不要省略。
那 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>Title</title>
</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)
最终结果可想而知,通过访问 127.0.0.1:8000/test_if 会得到如下显示:
注意:elif 和 else 这两个标签是可选的,elif 标签可以不止一个,但是 else 标签只有一个,同时也可以都不出现在 if 标签中,只使用 if 与 endif。
如果当判断的条件太多时,为了避免过多的连接操作符的出现,同样可以考虑使用嵌套的 if 标签。
格式如下所示:
{% if 条件表达式1 %}
{% if 条件表达式 %}
......
{% elif 条件表达式2 %}
......
{% else %}
......
{% endif %}
{% endif %}
在这里我们介绍另外一种方式来简单的演示如何使用嵌套 if 标签,在 views.py 文件中添加如下代码:
from django.template import Template, Context #调用template、以及上下文处理器方法
def Hello_MyWeb(request):
#调用template()方法生成模板
t = Template("""
{% if web.name == '乔治' %}
{% if printable %}
<h1>Hello 乔治</h1>
{% else %}
<h2>欢迎您下次访问,乔治</h2>
{% endif %}
{% endif %}
""")
c = Context({'web': {'name': '乔治'}, 'printable': True}) #Context必须是字典类型的对象,用来给模板传递数据
html = t.render(c)
return HttpResponse(html)
然后我们在 urls.py 文件中为 hello_MyWeb() 函数配置路由映射关系,如下所示:
path('Hello_MyWeb/',views.Hello_MyWeb)
最终我们会得到如下所示的输出:
当我们将 printable 的值改为 False 的时候,则会得到如下输出:
本节给大家详细的讲解了 Django 模板标签中的 if 标签的使用方法。在学习的过程一定要懂得融会贯通 ,因为 Django 是基于 Python 的 Web 框架,它纵然有自己的特点,但是万变不离其宗,所以学会结合 Python 语言去学习会有利我们快速理解与掌握相关的知识。
(2)Django for标签的使用
它的使用格式如下:
{% for 变量 in 可迭代对象 %}
... 循环语句
{% empty %}
... 可迭代对象无数据时填充的语句
{% endfor %}
我们通过一个具体的实例来看一下它的用法,在 views.py 中添加如下代码:
def test_for(request):
#调用template()方法生成模板
t1 = Template("""
{% for item in list %}
<li>{{ item }}</li>
{% empty %}
<h1>如果找不到你想要,可以来百度(网址:https://www.baidu.com)</h1>
{% endfor %}
""")
#调用 Context()方法
c1 = Context({'list': ['Python', 'Java', 'C', 'Javascript', 'C++']})
html = t1.render(c1)
return HttpResponse(html)
并配置路由映射关系,如下所示:
path('test_for/',views.test_for)
访问 127.0.0.1:8000/test_for 得到如下页面:
当我们将列表改为空的时候,或者不是一个可迭代对象的时候,会得到如下页面:
提示:与 Python 中的 for 循环不同的是,for 标签只能一次性地遍历完列表中的元素,不能中断(break),也不能跳过(continue)。
(3)for标签嵌套使用
for 标签同样可以嵌套使用,示例代码如下所示:
def test01_for(request):
#使用嵌套for标签依次遍历列表取值
website = Template("""
{% for course in list01 %}
<div>
{% for coursename in course %}
<p><b>{{ coursename }}</b></p>
{% endfor %}
</div>
{% endfor %}
""")
webname = Context({'list01': [['Django', 'Flask', 'Tornado'], ['c语言', 'Django官网', 'Pytho官网']]})
html = website.render(webname)
return HttpResponse(html)
并配置路由映射关系,如下所示:
path('test01_for/', views.test01_for)
(4)forloop变量详解
forloop 的属性主要有以下几个:
描述 | |
---|---|
forloop.counter | 用来计数,查看当前迭代第几个元素(从1开始索引) |
forloop.revcounter | 表示当前循环中剩余的未被迭代的元素数量(从1开始索引) |
forloop.first | 如果当前迭代的是第一个元素,则为True |
forloop.last | 如果当前迭代的是最后一个元素,则为True |
forloop.parentloop |
实例说明如下所示:
def test_forloop(request):
a = Template("""
{% for item in lists %}
<div>
<p><b>{{ forloop.counter }}:{{ item }}</b></p>
</div>
{% endfor %}
""")
b = Context({'lists': ['c语言', 'Django官网', 'Pytho官网']})
html = a.render(b)
return HttpResponse(html) # 数字与元素以 1:'c语言' 的形式出现
路由映射关系,如下所示:
path('test_forloop/', views.test_forloop),
最终效果如图所示: