模板
之前的案例中,能够返回简单的字符串信息给浏览器。那如果想要返回html
页面给浏览器该怎么做呢?
当然,我们可以这么写:
def index(request):
return HttpResponse('<h1 style="color:red">我是硬编码的</h1>')
这样显然,不便维护,也不高效。
django提供了一套模板渲染的机制,将html源码写在模板文件中,然后通过方法将数据渲染后返回给客户端。
模板路径设置
在项目根目录下创建一个templates
文件夹用来存放模板文件,然后将这个文件的路径配置到配置项TEMPLATES
的DIRS
中。
# study_django/settings.py
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [str(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',
],
},
},
]
注意要填写模板文件夹的绝对路径,通过代码str(BASE_DIR / 'templates')
可以动态生成。
模板渲染
模板渲染本质上就是将数据替换到模板文件的插槽中,和字符串替换一样。
模板变量
最简单的渲染是将变量替换到模板中。
在模板中,模板变量的语法是:
{{ 变量名 }}
在templates
文件中再创建一个crm
文件夹,然后在其中创建一个index.html
,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>{{ msg }}</p>
</body>
</html>
添加了一个模板变量msg
,这个变量需要从视图传递一个对应的变量进行替换。修改crm.index
视图如下:
# crm/views.py
from django.http import HttpResponse
from django.template.loader import get_template
def index(request):
msg = '我是首页面'
t = get_template('crm/index.html') # 获取模板
html = t.render(context={'msg': msg}) # 渲染html
return HttpResponse(html) # 返回响应
上面的代码非常简单,做了如下工作:
- 在视图中定义了一个变量
msg
, - 然后根据路径
crm/index.html
获取对应的模板, - 再将变量
msg
传递给模板进行渲染, - 最后将渲染好的html返回。
访问这个视图,返回页面如下:
上面的代码还可以通过一个快捷函数简化:
from django.shortcuts import render
def index(request):
msg = '我是首页面'
return render(request, 'crm/index.html', context={'msg': msg})
render
函数的第一个参数是请求request
,第二个参数是模板路径,第三个参数context
是要传递给模板的数据,是一个字典,其中key是模板上对应的变量名,值是实际要渲染的数据。
模板变量的解析规则
模板变量按照如下流程解析替换:
- 当模板引擎遇到模板变量时,它会计算该变量,并将其替换为结果
- 当模板引擎在变量中遇到
.
时(x.y的形式),它会按以下顺序尝试查找: - 字典键值查找
- 属性或方法查找
- 数字索引查找
- 如果结果是可调用的,则调用它时不带参数。调用结果成为模板值。
模板标签
只能简单渲染变量显然不满足需求,django的模板系统中还提供了模板标签来实现更多的渲染逻辑,例如判断,循环等。
下面列出几个常用的模板标签:
for
循环浏览数组中的每个项目,使该项目可以在上下文变量中可用。例如,要显示student_list
中提供的学生列表:
<ul>
{% for student in student_list %}
<li>{{ student.name }}</li>
{% endfor %}
</ul>
if
{% if %}
标签会判断给定的变量,当变量为 True 时(比如存在、非空、非布尔值 False),就会输出块内的内容:
{% if student_list %}
学生的数量: {{ student_list|length }}
{% else %}
没有学生
{% endif %}