【一】引子
来看一段代码
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
直接把HTML页面嵌套在视图函数里返回给浏览器并不是一个好主意;
原因:
- 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改,牵一发而动全身;
- Python 代码编写和 HTML 设计是两项不同的工作,前端开发和后端开发无非 并行;
基于这些原因,将HTML页面的设计和后端逻辑设计分离,会更简洁、容易维护开发我们的WEB应用。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式。这个就是DJango模板系统的意义所在。
【二】模板语法的传值
{{ }}
: 变量相关{% %}
: 逻辑相关
重要事项:
- 变量语法:在模板中使用变量时,使用双花括号
{{ }}
将变量包围起来,例如{{ variable_name }}
。 - 变量名称:变量名称由字母、数字、下划线和点号组成,不能以数字开头。
- 变量上下文:变量的值来自于视图函数中的上下文(context),在模板中可以直接访问视图函数中传递的变量。
- 对象属性:如果变量是一个对象,可以使用点号语法来访问对象的属性,例如
{{ object.attribute }}
。 - 字典和列表:可以使用方括号语法来访问字典和列表中的元素,例如
{{ my_dict["key"] }}
或{{ my_list[0] }}
。 - 过滤器:可以使用管道符号
|
将变量与过滤器组合,以修改变量的显示方式,例如{{ variable|filter_name }}
。 - 默认值:可以通过在变量后面添加
default
过滤器来提供默认值,以防变量不存在或为空,例如{{ variable|default:"N/A" }}
。
【1】 变量
(1)传值
- 在Django的模板语言中按此语法使用:
- {{ 变量名 }}。
- 当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。
- 变量的命名包括任何字母数字以及下划线 (“_”)的组合。
- 变量名称中不能有空格或标点符号。
(2)取值
- 点(.)在模板语言中有特殊的含义。
- 当模版系统遇到点(“.”),它将以这样的顺序查询:
- 字典查询(Dictionary lookup)
- 属性或方法查询(Attribute or method lookup)
- 数字索引查询(Numeric index lookup)
- 当模版系统遇到点(“.”),它将以这样的顺序查询:
总结:
通过在模板中使用双花括号{{ }}
来传递变量,并使用点.
来取值,您可以在模板中动态地显示来自视图函数的数据。
注意事项
- 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。
- 如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为’’ (空字符串) 。
简单的示例:
以下是Django模板系统中的八大数据类型的简单表示,并包括了urls.py路由层、views.py视图层和前端HTML的示例:
-
字符串(String):
- urls.py:无需特殊处理。
- views.py:将字符串传递给模板。
- HTML:直接在模板中使用变量。
示例:
# urls.py from django.urls import path from . import views urlpatterns = [ path('hello/', views.hello_view, name='hello'), ]
# views.py from django.shortcuts import render def hello_view(request): greeting = "Hello, World!" return render(request, 'hello.html', {'greeting': greeting})
<!-- hello.html --> <h1>{{ greeting }}</h1>
-
整数(Integer):
- urls.py:无需特殊处理。
- views.py:将整数传递给模板。
- HTML:直接在模板中使用变量。
-
浮点数(Float):
- urls.py:无需特殊处理。
- views.py:将浮点数传递给模板。
- HTML:直接在模板中使用变量。
-
列表(List):
- urls.py:无需特殊处理。
- views.py:将列表传递给模板。
- HTML:使用循环在模板中遍历列表元素。
-
字典(Dictionary):
- urls.py:无需特殊处理。
- views.py:将字典传递给模板。
- HTML:使用点号语法在模板中访问字典的键值对。
-
元组(Tuple):
- urls.py:无需特殊处理。
- views.py:将元组传递给模板。
- HTML:直接在模板中使用变量。
-
对象(Object):
- urls.py:无需特殊处理。
- views.py:将对象传递给模板。
- HTML:使用点号语法在模板中访问对象的属性或方法。
-
布尔值(Boolean):
- urls.py:无需特殊处理。
- views.py:将布尔值传递给模板。
- HTML:使用条件语句在模板中根据布尔值显示不同的内容。
具体示例:
# urls.py文件
path('index/',views.index)
# views.py
def index(request):
# 模板语法可以传递的后端python的数据类型
int = 123
float = 123.02
str_ = '老子明天不上班'
bool = True
list = ['一号技师','二号技师','三号技师']
tuple = (123,456,789,741,852,963)
dict = {'username':'xiaoshuai','age': 18,'slary': 10000}
set = {123,'数字','小明'}
return render(request, 'index.html',locals())
<!-- 在index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板层传值</title>
</head>
<body>
{{ int }} <br>
{{ float }}<br>
{{ str }}<br>
{{ bool }}<br>
{{ list }}<br>
{{ tuple }}<br>
{{ dict }}<br>
{{ set }}<br>
</body>
</html>
- 跟进上述来看跟保证输出成功的参数就是
locals()
return render(request, 'index.html',locals())
值得注意的是:
函数也能
-
def bai(): x = 6 y = 7 z = x + y return z
-
传递函数名会自动加括号调用 但是模板语法不支持给函数额外的参数:{{ bai }}
-
传类名的时候也会自动加括号调用(实例化){{ Myclass }} ,{{ obj }}
-
内部能够自动判断出当前的变量名是否可以加括号电影 如果可以就会自动执行 这针对是函数名跟类名。
-
{{ obj.get_bai }} <br> {{ obj.get_func }} <br> {{ obj.get_class }} <br>
-
对象被展示到html页面上 就类似于执行了打印操作也会触发
__self__方法
class Myclass(object):
def get_bai(self):
return 'sorry get_bai'
@staticmethod
def get_func():
return 'sorry get_func'
@classmethod
def get_class(cls):
return 'sorry clsssss'
def __str__(self):
return '也可以被执行'
obj = Myclass()
return render(request, 'index.html',locals())
取值
- 在Django模板语法的取值, 是固定的格式 只能采取
句点号 ( . )
<p> {{ dict.hobby.1 }}</p>
<p>{{ list.0 }}</p>
<p>{{ tuple.4 }}</p>
<p>{{ set.2 }}</p>
- 即可以点健也可以点索引, 还可以两者混用。
【三】过滤器
【1】过滤器
- 在Django的模板语言中,通过使用 过滤器 来改变变量的显示。
(1)过滤器的语法
{{ value|filter_name:参数 }}
{{ 数据|过滤器:参数 }}
- 使用管道符"|"来应用过滤器。
- 例如:
{{ name|lower }}
会将name变量应用lower过滤器之后再显示它的值。- lower在这里的作用是将文本全都变成小写。
(2)注意事项
- 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
- 过滤器可以接受参数,例如:
{{ sss|truncatewords:30 }}
,这将显示sss的前30个词。 - 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:
{{ list|join:', ' }}
|
左右没有空格!没有空格!没有空格!
Django的模板语言中提供了大约六十个内置过滤器。
【2】语法
{{数据|过滤器:参数}}
【3】Django中实战使用——常用的过滤器:
①项目目录下的views.py文件:
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime
def index(request):
test="THIS IS A LIST!"
list=["A","B","C","D","E"]
data={
'test':test,
'xx':'',
'num1':1,
'num2':2,
'list':list,
'now':datetime.now(),
'html':'<h1>hello django!!!</h1>',
'float':3.1415926
}
return render(request, "index.html", data)
②项目目录下templates模板文件夹下的模板文件index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试!</title>
</head>
<body>
{#没做处理的变量:#}
{{ test }}<br>
{#设置了默认值的变量 在这个值被django认为是False的时候会使用此默认值。比如:空字符串,None。#}
{{ xx|default:'xxxxx' }}<br>
{#设置了只有为None时才使用默认值的变量#}
{{ xx|default_if_none:'aaaaa'}}<br>
{#变为小写后的变量#}
{{ test|lower }}<br>
{#先变为小写再将首字母大写后的变量#}
{{ test|lower|capfirst }}<br>
{#两个数字变量相加 add:字符串相加,数字相加,列表相加,如果失败,将会返回一个空字符串#}
{{ num1|add:num2 }}<br>
{#两个字符串变量相加#}
{{ test|add:xx }}<br>
{#列表变量的第一个元素#}
{{ list|first }}<br>
{#列表变量的最后一个元素#}
{{ list|last }}<br>
{#默认的data日期时间格式#}
{{ now|date }}<br>
{#默认的time时间格式#}
{{ now|time }}<br>
{#这是data过滤器的年月日24小时制时间格式#}
{{ now|date:'Y/m/d/H:i:s' }}<br>
{#这是time过滤器的时分秒12小时制时间格式#}
{{ now|time:'h:i:s' }}<br>
{#这是字符串的join方法 跟python中join一样的用法#}
{{ list|join:'oooo' }}<br>
{#这是字符串的长度方法#}
{{ test|length }}<br>
{#这是列表的长度是否为4#}
{{ list|length_is:4 }}<br>
{#下面这俩有xxx.html类型的,针对html,截断标签中的字符,而不会截断标签#}
{#这是字符串只显示4个字符,其余省略(但是占3位)#}
{{ test|truncatechars:7 }}<br>
{#这是字符串只显示2个单词,其余省略(不占位)#}
{{ test|truncatewords:2 }}<br>
{#这是字符串的切片#}
{{ test|slice:'1:4' }}<br>
{#这是列表的切片#}
{{ list|slice:'2' }}<br>
{#这是含html标签的字符串#}
{{ html }}<br>
{#这是去掉字符串中的html标签#}
{{ html|striptags }}<br>
{#这是关掉自动转义,使字符串中html标签生效#}
{{ html|safe }}<br>
{#这是没做处理的小数#}
{{ float }}<br>
{#这是保留了一位小数#}
{{ float|floatformat }}<br>
{#这是保留了两位小数#}
{{ float|floatformat:'2' }}
</body>
</html>
【4】日期格式化(date)
(1)语法
- 格式化
{{ value|date:"Y-m-d H:i:s"}}
- 可用的参数:
格式化字符 | 描述 | 示例输出 |
---|---|---|
a | 'a.m.' 或'p.m.' (请注意,这与PHP的输出略有不同,因为这包括符合Associated Press风格的期间) | 'a.m.' |
A | 'AM' 或'PM' 。 | 'AM' |
b | 月,文字,3个字母,小写。 | 'jan' |
B | 未实现。 | |
c | ISO 8601格式。 (注意:与其他格式化程序不同,例如“Z”,“O”或“r”,如果值为naive datetime,则“c”格式化程序不会添加时区偏移量(请参阅datetime.tzinfo ) 。 | 2008-01-02T10:30:00.000123+02:00 或2008-01-02T10:30:00.000123 如果datetime是天真的 |
d | 月的日子,带前导零的2位数字。 | '01' 到'31' |
D | 一周中的文字,3个字母。 | “星期五” |
e | 时区名称 可能是任何格式,或者可能返回一个空字符串,具体取决于datetime。 | '' 、'GMT' 、'-500' 、'US/Eastern' 等 |
E | 月份,特定地区的替代表示通常用于长日期表示。 | 'listopada' (对于波兰语区域,而不是'Listopad' ) |
f | 时间,在12小时的小时和分钟内,如果它们为零,则分钟停留。 专有扩展。 | '1' ,'1:30' |
F | 月,文,长。 | '一月' |
g | 小时,12小时格式,无前导零。 | '1' 到'12' |
G | 小时,24小时格式,无前导零。 | '0' 到'23' |
h | 小时,12小时格式。 | '01' 到'12' |
H | 小时,24小时格式。 | '00' 到'23' |
i | 分钟。 | '00' 到'59' |
I | 夏令时间,无论是否生效。 | '1' 或'0' |
j | 没有前导零的月份的日子。 | '1' 到'31' |
l | 星期几,文字长。 | '星期五' |
L | 布尔值是否是一个闰年。 | True 或False |
m | 月,2位数字带前导零。 | '01' 到'12' |
M | 月,文字,3个字母。 | “扬” |
n | 月无前导零。 | '1' 到'12' |
N | 美联社风格的月份缩写。 专有扩展。 | 'Jan.' ,'Feb.' ,'March' ,'May' |
o | ISO-8601周编号,对应于使用闰年的ISO-8601周数(W)。 对于更常见的年份格式,请参见Y。 | '1999年' |
O | 与格林威治时间的差异在几小时内。 | '+0200' |
P | 时间为12小时,分钟和’a.m。'/‘p.m。’,如果为零,分钟停留,特殊情况下的字符串“午夜”和“中午”。 专有扩展。 | '1 am' ,'1:30 pm' / t3>,'midnight','noon','12:30 pm' / T10> |
r | RFC 5322格式化日期。 | 'Thu, 21 Dec 2000 16:01:07 +0200' |
s | 秒,带前导零的2位数字。 | '00' 到'59' |
S | 一个月的英文序数后缀,2个字符。 | 'st' ,'nd' ,'rd' 或'th' |
t | 给定月份的天数。 | 28 to 31 |
T | 本机的时区。 | 'EST' ,'MDT' |
u | 微秒。 | 000000 to 999999 |
U | 自Unix Epoch以来的二分之一(1970年1月1日00:00:00 UTC)。 | |
w | 星期几,数字无前导零。 | '0' (星期日)至'6' (星期六) |
W | ISO-8601周数,周数从星期一开始。 | 1 ,53 |
y | 年份,2位数字。 | '99' |
Y | 年,4位数。 | '1999年' |
z | 一年中的日子 | 0 到365 |
Z | 时区偏移量,单位为秒。 UTC以西时区的偏移量总是为负数,对于UTC以东时,它们总是为正。 | -43200 到43200 |
【5】取消转义(mark_safe和safe)
- Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。
- 但是有的时候我们可能不希望这些HTML元素被转义
- 比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。
- 以后在写全栈项目时,前端代码不一定必须在前端页面书写
- 也可以选择先在后端写好,再传递给前端页面展示
(1)前端转义(safe)
msg = '<h1>鸡你太美</h1>'
<p>转义字符(不转义) {{ msg }}</p>
<p>转义字符(转义) {{ msg|safe }}</p>
转义字符(不转义) <h1>鸡你太美</h1>
转义字符(转义)
鸡你太美(已变成h1标题格式)
(2)后端转义(mark_safe)
from django.utils.safestring import mark_safe
res = mark_safe('<h1>坤坤</h1>')
<p>转义字符(转义) {{ res }}</p>
转义字符(转义)
坤坤(已变成h1标题格式)
-
前端
-
msg = '<h1>你太美</h1>'
-
{{ 值| safe}}
-
-
后端
-
from django.utils.safestring import mark_safe
-
res = mark_safe("<h1>你太美</h1>")
-
转义字符(转义) {{ msg|safe }}
转义字符(不转义)鸡你太美
转义字符(转义)
鸡你太美(已变成h1标题格式)
### (2)后端转义(mark_safe)
```java
from django.utils.safestring import mark_safe
res = mark_safe('<h1>坤坤</h1>')
<p>转义字符(转义) {{ res }}</p>
转义字符(转义)
坤坤(已变成h1标题格式)
-
前端
-
msg = '<h1>你太美</h1>'
-
{{ 值| safe}}
-
-
后端
-
from django.utils.safestring import mark_safe
-
res = mark_safe("<h1>你太美</h1>")
-