在访问网站,例如博客时,整个html页面的骨架是固定样式的,而内容文章会发生变化,整个html的骨架文件,我们称为模板文件,向模板中加入内容称为模板渲染。
在讲解模板渲染前,先看一下django用于返回http请求结果给浏览器的常见处理函数:
from django.shortcuts import render, redirect
from django.http import HttpResponse
def index(request):
return HttpResponse("hello world!")
def index(request):
return redirect("/helloworld")
from django.shortcuts import render
def my_view(request):
# View code here...
return render(request, 'myapp/index.html', {
'foo': 'bar',
}, content_type='application/xhtml+xml')
通过HttpResponse实现render的功能,可以达到与render相同的功能,案例如下:
from django.http import HttpResponse
from django.template import loader
def my_view(request):
t = loader.get_template('myapp/index.html')
c = {'foo': 'bar'}
return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
通过python的locals()代替render中的字典参数,locals()会将当前视图函数的所有对象加载到模板当中,会浪费系统内存资源:
def my_view(request):
return render(request,'page.html',locals())
通过上面的案例,我们可以看到django不同的返回函数的功能,通常我们用render()函数来进行渲染模板并返回给浏览器。
创建新的项目mysite与应用myapp
django-admin startproject mysite
cd mysite
python3 manage.py startapp myapp
安装应用,mysite/settings.py
[root@work1 mysite]# vim mysite/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', #<--增加一行
]
创建templates目录用于存储模板文件,并配置mysite项目找到模板目录:
[root@work1 mysite]# mkdir templates
[root@work1 mysite]# vim mysite/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #< -- 要修改的内容,这样django能找到模板文件
'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',
],
},
},
]
配置urls.py
[root@work1 mysite]# vim mysite/urls.py
from django.contrib import admin
from django.urls import path, include #<--增加include
urlpatterns = [
path('myapp/',include('myapp.urls')), #<--通过include,包含myapp的urls.py
path('admin/', admin.site.urls),
]
[root@work1 mysite]# vim myapp/urls.py #编辑新文件
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
添加myapp.views.index视图
[root@work1 mysite]# vim myapp/views.py
from django.shortcuts import render
def index(request):
var1= 'hello world'
list1=['第一','第二','第三']
dict1={'username':'zhangsan', 'password':'121'}
return render(request,'myapp.html',locals())
编辑模板文件,在模板中渲染var1变量,通过{{ var_name }}来引用具体变量或者具体类实例的某个属性。
[root@work1 mysite]# vim templates/myapp.html
<!DOCTYPE html>
<html>
<head>
<title>django</title>
</head>
<body>
<h3>var1: {{ var1 }}</h3>
<p>list1: {{ list1 }}</p>
<p>dict1: {{ dict1 }}</p>
<p>{{ dict1.username }}</p>
</body>
</html>
# 运行django服务,访问http://你的IP:PORT/myapp查看页面效果。
在django模板中,可以通过for循环,遍历字典、列表、或者数据查询all()/filter()返回的集合。修改myapp.html,实现在模板中使用for循环遍历。
[root@localhost mysite]# vim templates/myapp.html
<!DOCTYPE html>
<html>
<head>
<title>django</title>
</head>
<body>
{% for l in list1 %}
<p>{{ forloop.counter }} : {{ l }}</p>
{% endfor %}
{% for k,v in dict1.items %}
<h3>{{ k }}: {{ v }}</h3>
{% endfor %}
</body>
</html>
# 运行django服务,访问http://你的IP:PORT/myapp查看页面效果。forloop
forloop是可以在django模板中引用的for循环计数变量.(通常用于特殊处理,例如页面元素增加特殊属性)
属性 | 含义 |
---|---|
.counter | 表示当前迭代次数,从1开始计数 |
.counter0 | 表示当前迭代次数,从0开始计数 |
.first | 布尔值,是否是第一循环 |
.last | 布尔值,判断是否是最后一次循环 |
.parentloop | for循环嵌套使用时,获取上层循环 |
在django模板中使用if判断,注意==两边空格。修改并编辑templates/myapp.html如下
<!DOCTYPE html>
<html>
<head>
<title>django</title>
</head>
<body>
{% for l in list1 %}
{% if l == "第一" %}
<p> 这是第一</p>
{% elif l == "第二" %}
<p> 这是第二</p>
{% else %}
<p> 这是第三</p>
{% endif %}
{% endfor %}
</body>
</html>
还可以使用!=, >=, <=, >, < ;可以使用and, or 连接多个判断条件not, in, not in;还可以使用and, or, not, in, not in ;还可以使用{% ifequal var1 var2 %} {% ifnotequal var1 var2 %} 等
编辑templates/base.html
<!DOCTYPE html>
<html>
<head>
<style>
.header {
background-color:black;
color:white;
text-align:center;
padding:5px;
}
#nav {
line-height:30px;
background-color:#eeeeee;
height:300px;
width:100px;
float:left;
padding:5px;
}
#content {
width:350px;
float:left;
padding:10px;
}
#footer {
background-color:black;
color:white;
clear:both;
text-align:center;
padding:5px;
}
</style>
</head>
<body>
{% include 'header.html' %}
{% include 'nav.html' %}
<div id="content">
<h2>标题</h2>
<p>主要内容</p>
</div>
{% include 'footer.html' %}
</body>
</html>
编辑include子页面header.html ,header.html ,header.html
[root@localhost mysite]# vim templates/header.html
<div class="header">
<h1>{{ var1 }}</h1>
</div>
[root@localhost mysite]# vim templates/header.html
<div id="nav">
<ul>
<li>垂直导航</li>
</ul>
</div>
[root@localhost mysite]# vim templates/header.html
<div id="footer">
底部
</div>
[root@localhost mysite]# vim myapp/views.py
from django.shortcuts import render
def index(request):
var1= 'hello world'
list1=['第一','第二','第三']
dict1={'username':'zhangsan', 'password':'121'}
return render(request,'base.html',locals()) #< 修改返回base.html
运行django服务,并访问http://你的IP:PORT/myapp
通过include with传递变量,修改base.html文件增加一行{% include 'header.html' with var1='1111' %},查看效果。
{% include 'header.html' %}
{% include 'header.html' with var1='1111' %}
修改templates/base.html
<!--#删除下面的内容-->
<!--
<div id="content">
<h2>标题</h2>
<p>主要内容</p>
</div>
-->
<!--#增加下面的内容-->
{% block content %}
{% endblock %}
新建并编辑templates/content.html
{% extends 'base.html' %}
{% block content %}
<div id="content">
<h2>标题</h2>
<p>主要内容</p>
</div>
{% endblock %}
修改视图,返回content.html
[root@localhost mysite]# vim myapp/views.py
from django.shortcuts import render
def index(request):
var1= 'hello world'
list1=['第一','第二','第三']
dict1={'username':'zhangsan', 'password':'121'}
return render(request,'content.html',locals()) #要修改的地方
运行django服务,并访问http://你的IP:PORT/myapp
过滤器的作用是对模板变量进行格式化的输出,案例如下:
#修改index视图
[root@localhost mysite]# vim myapp/views.py
from django.shortcuts import render
import datetime
def index(request):
var1= 'hello world'
list1=['第一','第二','第三']
dict1={'username':'zhangsan', 'password':'121'}
addvar=1
filesizeformatvar=123456789
slicevar='hello world'
datevar=datetime.datetime.now()
lowervar="ABC"
safevar="<a href='#'>这是一个safe过滤器测试</a>"
return render(request,'content.html',locals())
#修改content.html文件
{% extends 'base.html' %}
{% block content %}
<div id="content">
<h2>标题1</h2>
<p>主要内容1</p>
<p>{{ aa|default:"过滤器默认值"}}</p>
<p>{{ filesizeformatvar|filesizeformat}}</p>
<p>{{ addvar|add:"100"}}</p>
<p>{{ slicevar|slice:":2"}}</p>
<p>{{ datevar|date:"Y-m-d"}}</p>
<p>{{ lowervar|lower}}</p>
<p>{{ safevar|safe}}</p>
</div>
{% endblock %}
运行django服务,并访问http://你的IP:PORT/myapp
常用过滤器及含义:
过滤器名称 | 作用 |
---|---|
add | 字符串相加,数字相加,列表相加,如果失败,将会返回一个空字符串。 |
default | 提供一个默认值,在这个值被django认为是False的时候使用。比如 |
first | 返回列表中的第一个值。 |
last | 返回列表中的最后一个值。 |
date | 格式化日期和时间。 |
time | 格式化时间。 |
join | 跟python中的join一样的用法。 |
length | 返回字符串或者是数组的长度。 |
length_is | 字符串或者是数组的长度是否是指定的值。 |
lower | 把所有字符串都编程小写。 |
truncatechars | 根据后面给的参数,截断字符,如果超过了用…表示。 |
truncatewords | 同truncatechars,这个是以一个单词为单位进行截断。 |
capfirst | 首字母大写。 |
slice | 切割列表。用法跟python中的切片操作是一样的,区间是前闭合后开放。 |
striptags | 去掉所有的html标签。 |
safe | 关闭变量的自动转义 |
floatformat | 浮点数格式化。 |
过滤器可以自己定义。
自定义模板全局变量可以在所有的模板中直接使用,案例如下:
#编辑settings.py增加"'myapp.context_processors.mytest',",如下
[root@localhost mysite]# vim mysite/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(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',
'myapp.context_processors.mytest', #< -- 新增
],
},
},
]
#编辑并增加全局变量处理函数
[root@localhost mysite]# vim myapp/context_processors.py
def mytest(request):
context = {'testvar1': 'testvar1', 'testvar2': 'testvar2'}
return context
# 修改模板
[root@localhost mysite]# vim templates/content.html
{% extends 'base.html' %}
{% block content %}
<div id="content">
<h2>标题1</h2>
<p>主要内容1</p>
<p>{{testvar1}}</p>
</div>
{% endblock %}
运行django服务,并访问http://你的IP:PORT/myapp,可以看待testvar1在视图中没有,但是模板中可以直接使用。这里你可以理解settings.py中TEMPLATES中的context_processors的作用。
总结:本章节介绍了django常用的视图返回函数、render模板渲染函数,模板标签if/for/with、模板包含与继承、模板过滤器、模板全局变量。实际上常用模板标签除了if/for还有:autoescape设置标签的自动转义, 关闭自动转义,spaceless去除html代码中的空白字符,url标签等,你可以自定义模板标签来实现你需要的功能;也可以自定义过滤器实现自己的功能,这里不再详细介绍自定义的内容。