一.配置模板引擎
Django项目通过模板引擎解释模板文件,一个Django项目中可以配置一个或多 个模板引擎。Django有内置的模板引擎,在创建项目时,配置文件settings.py的TEMPLATES变量中会添加默认设置。
模板引擎:就是数据渲染到字符串的工具/将变量数据渲染到按照模板语法书写的文本的工具
使用终端控制台创建项目chapter02
django-admin startproject chapter02
setting.py文件中templates项目默认项目:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
- BACKEND:实现Django模板引擎API的模板引擎类的路径。
- DIRS:设置模板源文件的目录列表,模板引擎将按列表中元素的顺序依次查找目录
- APP_DIRS:声明是否在已安装的应用程序中查找模板。
- OPTIONS:模板引擎的设置信息,dict 类型
Django的默认模板引擎为django.template.backends.django.DjangoTemplates,其语法为Django模板语言。Django 项目也支持目前广泛的模板引擎是Jinja2。
模板配置中的 APP DIRS默认值为True,表示模板引擎将在项目的所有应用目录中搜索模板文件。也可以在DIRS选项中指定搜索路径。Django 会按照DIRS选项中路径的先后顺序搜索模板文件。
根目录下创建文件夹templates,html
templates文件下创建base.html在DIRS中进行添加路径
BASE_DIR指向当前目录路径
创建应用app
python manage.py startapp app
在应用app中创建文件夹templates,名字不能更改,必须是templates.
APP_DIR为True会去按照顺序dir 查找然后去应用的templates中查找
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'html')],
#按照顺序进行查找
'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',
],
},
},
]
二.使用模板类
调用模板类的构造函数Templare(),可以快速创建模板对象。调用模板render()方法,可以将模板渲染为HTML代码。
#首先进入环境
python manage.py shell
#调用模板类的构造函数
from django.template import Template
from django.template import Context
t=Template("你的名字是:{{name}}")
context=Context({'name':"zhangsan"})
t.render(context)
三.使用模板文件
1.定义模板文件time.html文件
在应用目录下创建templates文件夹,在文件夹内创建time.py文件,下列模板显示视图传递时间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DEMO1</title>
</head>
<body>
<h1>{{time}}</h1>
</body>
</html>
2.定义使用模板的视图函数
四种方法:
1.get_template 2.render_to_string 3.TemplatesResponse 4.render
from datetime import datetime
from django.shortcuts import render
from django.http import HttpResponse
#get_template
from django.template.loader import get_template
time = datetime.today()#准备数据
def demo1(request):
t=get_template('time.html')#载入模板文件
html=t.render({'time':time}) #渲染模块
return HttpResponse(html) #将模块渲染结果返回客户端
#render_to_string
from django.template.loader import render_to_string
def demo2(request):
str_response = render_to_string('time.html',{'time':time})
return HttpResponse(str_response)
#TemplatesResponse
from django.template.response import TemplateResponse
def demo3(request):
time=datetime.today()
return TemplateResponse(request,'time.html',{'time':time})
#render
def demo4(request):
time=datetime.today()
return render(request,'time.html',{'time':time})
3.配置URL
根路由:
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('demo1',views.demo1),
path('demo2',views.demo2),
path('demo3',views.demo3),
path('demo4',views.demo4),
]
启动项目服务器
四.变量
模板变量用于标识模板中会动态变化的数据,当模板被渲染时,模板引擎将其替换为视图中传递而来的真实数据。
{{ variable }}
模板变量名由字母、数字和下画线(“_”)组成,但不能以下画线开头。
模板语言通过点字符(“.”)进一步访问变量中的数据,但由于模板不明确模板变量的类型,因此模板引擎会按以下顺序进行尝试。
- 将变量视为字典,尝试根据键访问变量的值。
- 将变量视为对象,尝试访问变量的属性或方法
- 尝试访问变量的数字索引。
需要注意的是,若点字符后是一个方法,这个方法在调用时不带括号。
五.过滤器
过滤器用于过滤变量,获取更精确的数据,其语法格式如下:
{{ variables|filters }}
使用多个管道符号(“|”)连接多个过滤器,连续对同一变量进行过滤,其语法格式如下:
{{ variables|filters1|filters2... }}
需要注意的是,管道符号和变量、过滤器之间不能有空格。
1.常 用 的 模 板 过 滤 器
2.常用过滤器
创建模板文件demo5.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
add1:{{a|add:"32"}},<br>
add2:{{ b|add:second}},<br>
addslashes:{{ c|addslashes }},<br>
capfirst:{{ d|capfirst }},<br>
cut:{{ f|cut:" "}},<br>
date:{{g|date:"Y年m月d日"}},<br>
default:{{h|default:"35"}},<br>
dictsort:{{ i|dictsort:"age"}},<br>
escape:{{j|escape}},<br>
</p>
</body>
</html>
定义使用模板的视图文件
def demo5(request):
add1=[1,2,3]
add2=[4,5,6]
time=datetime.now()
value=[ {'name':'张三','age':19},
{'name':'李四','age':32},
{'name':'王五','age':21},]
c={'a':66,'b':add1,'second':add2,'c':"This is my compture.",'d':"laura",'f':"he ll o world",'g':time,'h':"",'i':value,'j':'<a&sd>',}
return render(request,'demo5.html',c)
根路由:
path('demo5',views.demo5)
启动项目服务器
2.1常用过滤器
创建模板文件demo6.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
filesizeformat:{{k|filesizeformat}},<br>
join:{{ l|join:" // "}},<br>
linenumbers"{{ m|linenumbers}},<br>
length:{{ n|length }},<br>
lower/upper:{{ o|lower }},<br>
random:{{ p|random }},<br>
truncatewords:{{ q|truncatewords:2}},
</p>
</body>
</html>
定义使用模板的视图文件
def demo6(request):
a={'k':123456789,'l':[1,2,3],'m':18,'n':"adsdffddd",'o':"ABJS",'p':[2,4,56,7],'q':"hello world,my name is myy"}
return render(request,'demo6.html',a)
配置根路由:
path('demo6',views.demo6)
启动项目服务器
六.标签
- 标签蕴含一定的逻辑,它的功能要比变量复杂,例如一些标签用于输出文本;一些标签通过执行循环或逻辑控制流;一些标签加载外部信息到模板中,以供后续变量的使用。
- 标签格式简单,例如:{% tag %};也有一些标签必须成对出现,以标识模板文本的开始和结束,示例格式如下:
{% tag %} ... {% endtag %}
1.常用的模块标签
2.for标签
创建模板文件demo7.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
<!-- 使用for标签遍历书单book_list,并输出所有书名 -->
{% for r in data %}
<!-- 模板中的for支持反向遍历列表 -->
{% for r in data reversed%} //二选一
<tr></tr>
<li>{{r}}</li>
{% endfor %}
</p>
</body>
</html>
定义使用模板的视图文件
def demo7(request):
data=['骆陀祥子','西游记','斗罗大陆']
return render(request,'demo7.html',{'data':data})
配置URL(根路由):
path('demo7',views.demo7)
启动项目服务器
2.1 Django为for循环定义了一些变量
2.2双层列表
若要遍历双层列表,可以解包内层列表中的每个元素到多个变量中
创建模板文件demo8.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
{% for r in data %}
第{{forloop.counter}}行:
{%for a in r%}
<li>{{a}}</li>
{%endfor%}
{%endfor%}
</p>
</body>
</html>
定义使用模板的视图文件
def demo8(request):
data=[[1,2,3],[4,5,6],['a','b','c','d']]
return render(request,'demo8.html',{'data':data})
配置URL(根路由):
path('demo8',views.demo8),
遍历双层列表的操作在遍历字典时同样适用。示例代码如下:
创建模板文件demo9.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
{% for k,v in data.items %}
<li>{{k}}={{v}}</li>
{%endfor%}
</p>
</body>
</html>
定义使用模板的视图文件
def demo9(request):
data = {'name':'zhangsan','age':30}
return render(request,'demo9.html',{'data':data})
配置URL(根路由):
path('demo9',views.demo9),
需要注意的是,操作符“.”查找优先于方法查找,因此若字典中包含键items,data.items将返回data[‘items’]而非data.items()。
3.for...empt
for循环可以使用可选的{%empty%}子句,若给定的数组为空或无法找到,则显示{%empty%}子句的文本。
创建模板文件test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{% for r in data%}
<tr></tr>
<li>{{r}}</li>
{% empty %}
<li>抱歉,图书列表为空</li>
{% endfor %}
</body>
</html>
定义使用模板的视图文件
def test(request):
data=[]
return render(request,'test.html',{'data':data})
配置URL(根路由):
path('test',views.test),
4.if/elif/else
if/elif/else是条件判断标签,与Python中的if、elif、else含义相同,若条件为True,显示相应子句中的内容。
创建模板文件test1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
分数:{{data}}
班级:{{cls1}}
{% if data >= 90%}
等级:A
{% elif data >= 80%}
等级:B
{% elif data >= 60%}
等级:C
{%else%}
等级:D
{%endif%}
</p>
</body>
</html>
定义使用模板的视图文件
def test1(request):
data=80
cls1="211"
return render(request,'test1.html',{'data':data})
配置URL(根路由):
path('test1',views.test1),
需要注意的是,模板语言的if标签不支持括号,若需明确表示混合语句中子句的优先级,应使用if嵌套语句。
5.include
在使用include标签时需为其传入置于单/双引号中的变量或硬编码字符串,或指示模板的变量。
{% include "foo/bar.html" %}
{% include template_name %}
创建模板文件test2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
引入模块:{% include 'test1.html' %}<br>
当前模块:当前日期{% now "Y年f月j日 H:i:s"%}
</p>
</body>
</html>
j也代表日期,与d的区别在于其前面不加0。M与小写m的区别是其以英文缩写显示月份,而不是数字。另外F也代表月份,为英文月份全称。
定义使用模板的视图文件:
def test2(request):
data=90
cls1='985'
return render(request,'test2.html',{'data':data,'cls1':cls1})
配置URL(根路由):
path('test2',views.test2),
include标签可以在加载模板的同时利用关键字with为模板传递变量。
{% include "name_snippet.html" with person="Jane" greeting="Hello" %}
创建模板文件test3.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
引入模块:{% include 'test1.html' with data=100 %}
当前模块:当前日期{% now "Y年f月j日 H:i:s"%}
</p>
</body>
</html>
定义使用模板的视图文件:
def test3(request):
data=90
cls1='985'
return render(request,'test3.html',{'data':data,'cls1':cls1})
配置URL(根路由):
path('test3',views.test3),
若只希望使用提供的变量(或不使用变量)渲染上下文,需使用only选项。
{% include "name_snippet.html" with greeting="Hi" only %}
创建模板文件test4.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>
引入模块:{% include 'test1.html' with data=50 only %}
当前模块:当前日期{% now "Y年f月j日 H:i:s"%}
</p>
</body>
</html>
定义使用模板的视图文件:
def test4(request):
data=90
cls1='985'
return render(request,'test4.html',{'data':data,'cls1':cls1})
配置URL(根路由):
path('test4',views.test4),
七.自定义过滤器和标签
自定义的过滤器和标签通常位于应用目录中的包templatetags,在templatetags包中创建文件,在文件中自定义过滤器和标签。
1.自定义过滤器
第一步:创建新的应用booklist
python manage.py startapp booklist
第二步:在booklist创建文件夹templateags
第三步:在templateags中创建filters.py
import datetime
#为了使自定义过滤器和标签生效,templatetags下的过滤器文件必须包含模块级变量register
from django import template
register = template.Library()
def sum(value, arg):
return value + arg
register.filter('sum',sum)
@register.filter(name='examp')
def examp(value, arg):
return str(value) + str(arg)
@register.filter
def examp(value, arg):
return str(value) + str(arg)
需要说明的是,模板系统旨在展示内容,而非规定程序逻辑,自定义过滤器与标签时也应尽量遵循此宗旨。下面将分别介绍如何自定义过滤器和标签,以及如何使用自定义的过滤器和标签。
第四步:在templates文件下创建demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>demo51</title>
</head>
<body>
<p>
add1:{{a|add:'32'}},<br>
add2:{{b|add:'second}'},<br>
addslashes:{{c|addslashes}},<br>
capfirst:{{d|capfirst}},<br>
cut:{{f|cut:" "}},<br>
date:{{g|date:"y月x日"}},<br>
default:{{h|default:"35"}},<br>
dictsort:{{i|dictsort:"age"}},<br>
escape:{{j|escape}},<br>
{% load filters %}
filter:{{data|examp:4}}
filter2:{{data|examp:5}}
</p>
</body>
<html>
第五步:写入视图函数views.py
from django.shortcuts import render
from datetime import datetime
# Create your views here.
def demo(request):
add1=[1,2,3]
add2=[4,5,6]
time=datetime.now()
value=[ {'name':'张三','age':19},
{'name':'李四','age':32},
{'name':'王五','age':21},]
c={'a':66,'b':add1,'second':add2,'c':"This is my compture.",'d':"laura",'f':"he ll o world",'g':time,'h':"",'i':value,'j':'<a&sd>','data':4}
return render(request,'demo5.html',c)
第六步:配置路由
path('demo',views.demo)
2.自定义标签
simple_tag()是django.template.Library的一个方法,它接收一个包含任意个参数的函数,将其包装后注册到模板系统中。
第一步:写入templateages中的filters.py文件
import datetime
from django import template
register = template.Library()
def get_current_time(timezone, format_string):
return datetime.datetime.now(timezone).strftime(format_string)
@register.simple_tag(takes_context=True)
def current_time(context, format_string):
timezone = context['timezone']
# get_current_time()是自定义的获取当前时间的方法
return get_current_time(timezone, format_string)
第二步: 写入视图函数views.py
from django.shortcuts import render
from datetime import datetime
from dateutil import tz
def demo1(request):
context = {
"format_string": "%b %d %Y %H:%M:%S",
# "timezone": tz.gettz('Asia/Shanghai'),
"timezone": tz.gettz('Europe/London'),
}
return render(request, 'demo1.html', context)
第三步:配置根路由
path('demo1',views.demo1),
第四步:在文件夹templates中建立demo1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="custom-label">
{% load filters %}
{% current_time format_string %}
</div>
</body>
</html>
下载插件
pip install python-dateutil
八.模板继承
模板继承机制使用模板系统中的block标签和extends标签实现,其中block标签标识与继承机制相关的代码块,extends指定子模板所继承的模板。子模板可以通过继承获取父模板中的内容。
父模块{%block%}标签,子模块用{extend%}标签。
父模块(base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{block title%}页面</title>
</head>
<body>
{%block header%}
<h1>标题</h1>
{%endblock header%}
{%block main %}
<h2>页面内容</h2>
{% endblock %}
<br><br><br>
{% block footer%}
<div class="footer no-mp">
<div class="foot_link">
<a href="#" id="">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRiht @2019 北京小鱼商业股份有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备******8号</p>
</div>
{%endblock%}
</body>
</html>
子模块(detail.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{% extends 'base.html'%}
{%block title %}
列表页面
{%endblock%}
{%block header%}
<h1>书单</h1>
{%endblock header%}
{%block main%}
<a href="#">1.《鲁迅作品全集》</a><br>
<a href="#">2.《秋雨散文集》</a><br>
<a href="#">1.《黑暗森林》</a><br>
<a href="#">1.《月亮与六便士》</a><br>
{% endblock main %}
</body>
</html>
配置视图文件(views.py):
from django.shortcuts import render
# Create your views here.
def show_detail(request):
return render(request,'detail.html')
def show_base(request):
return render(request,'base.html')
配置路由文件(urls.py):
from django .urls import path
from .import views
urlpatterns = [
path('show_detail',views.show_detail),
path('show_base',views.show_base),
]