众所周知,Django采用的是MTV框架模式,本文介绍的就是其中的T(Template模板)。对于模板引擎,比较有名的有DTL和Jinja2等,Django使用的则是DTL(Django Template Language),虽然也可以配置Django项目使用别的模板引擎,但是推荐使用Django自带的DTL。DTL模板是一种含有特殊语法的HTML文件,在Django中,这种文件会先被DTL模板引擎预编译为一个普通的HTML文件,然后再发送到客户端。
一、render传参(模板变量)
使用render 返回HTML模板时,给render 的参数context 指定一个字典,字典的key对应HTML模板中使用的变量,key对应的value则是该变量的值,在HTML模板中使用语法{{ key }} 即可。如果key对应的value是一个对象,也可以使用{{ key.attr_name }} 的形式获取对象的属性等信息。
"""视图函数"""
from django.shortcuts import render
def index(request):
context = {
'username': 'Hello world!'
}
# 给render的context参数指定一个字典并将其传入到HTML模板中
return render(request,'index.html',context=context)
<body>
{{ username }}
</body>
其他用法:
- 对象嵌套:例如字典中的value也是一个字典,想要获取这个嵌套字典中的value,直接使用点号即可
{{ key.sub_key }} 。
- 获取列表中的某个元素:使用形如
{{ list.0 }} 表示获取列表的第0个元素,想要获取其他的元素,也是类似的用法。
二、模板标签
模板标签就相当于在HTML模板中使用的“Python代码”,但是需要注意,所有的标签语法都需要包裹在{% %} 中,并且大多标签都有其对应的闭合标签,闭合标签通常是“end+标签名”的形式,如if 的闭合标签为endif 。
if标签
相当于Python中的if 语句,有对应的elif 和else 语句,同样也可以使用==,!=,<,<=,>,>=,in,not,is,is not 等判断运算符,对应的闭合标签为endif 。
{% if age < 18 %}
<p>未成年</p>
{% elif age == 18 %}
<p>刚成年</p>
{% else %}
<p>已成年</p>
{% endif %}
for标签
相当于Python中的for 语句,基本结构为for...in...empty ,如果遍历的对象中没有值,则会执行empty 标签中的内容,对应的闭合标签为endfor 。 注:DTL模板语法中的for 标签是没有continue 和break 语句的。
示例:正序遍历
<ul>
{% for book in books %}
<li>{{ book }}</li>
{% empty %}
<li>没有书籍!</li>
{% endfor %}
</ul>
示例:反序遍历(在遍历的对象后面添加一个reversed 关键字)
<ul>
{% for book in books reversed %}
<li>{{ book }}</li>
{% endfor %}
</ul>
示例:遍历字典,可以使用字典对应的keys 、values 和items 等方法,但是注意方法名后面没有Python中表示执行的括号。
{% for key,value in person.items %}
<p>key: {{ key }}</p>
<p>value: {{ value }}</p>
{% endfor %}
在for 循环中,DTL提供了一个forloop 变量来查询此for 循环的一些信息:
-
forloop.counter :当前循环的下标,以1开始。
-
forloop.counter0 :当前循环的下标,以0开始。
-
forloop.revcounter :forloop.counter 的反向下标。
-
forloop.revcounter0 :forloop.counter0 的反向下标。
-
forloop.first :是否是第一次遍历。
-
forloop.last :是否是最后一次遍历。
-
forloop.parentloop :如果有多重for 循环,那么这个属性代表当前循环的上一个循环。
with标签
with 标签是用来在HTML模板中定义变量的,形如{% with var_name=value %}...{% endwith %} 或者{% with value as var_name %}...{% endwith %} ,注意,如果使用等号= 的方式,那么等号= 两边不能有空格,对应的闭合标签为endwith 。 注:with 中定义的变量只能在对应的with 语句块中使用。
"""视图函数"""
from django.shortcuts import render
def index(request):
context = {
'persons': ['张三','李四']
}
return render(request,context=context)
{% with person.1 as lisi %}
<p>{{ lisi }}</p>
{% endwith %}
url标签
url 标签的作用就相当于from django.shortcuts import reverse ,用于通过URL名称反转为对应的URL,区别在于,reverse 用在Python文件中,url 标签则用在HTML模板文件中。
示例:普通用法,使用{% url 'url_name' %} 的方式。
urlpatterns = [
path('book/',views.book,name='book')
]
<ul>
<li><a href="/">首页</a></li>
<li><a href="{% url 'book' %}">读书</a></li>
</ul>
示例:通过url 标签传参,在url 标签语句后面添加需要的参数即可,多个参数之间使用空格分隔。
<li><a href="{% url 'book' book_id='1' %}">读书</a></li>
示例:通过url 标签传入查询字符串,和reversed 的使用类似,需要手工拼接查询字符串。
<li><a href="{% url 'book' %}?book_id=1">读书</a></li>
spaceless标签
此标签会移除HTML标签之间的空白字符,包括空格、tab键、换行等,闭合标签为endspaceless 。 注:此标签不会移除HTML标签内本身的内容。
以下代码:
{% spaceless %}
<p>
<a href="foo/"> Foo </a>
</p>
{% endspaceless %}
渲染完成后,变为:
<p><a href="foo/"> Foo </a></p>
autoescape标签
此标签表示自动转义功能,默认是开启的(on),表示将HTML中的特殊字符转义为HTML语法中的字符表示,如将< 转义为< 等,这意味着,字符串中的这些字符不会当成HTML语法来进行渲染加载,而是当成了普通字符,如果关闭自动转义功能(off),则会将字符串中的特殊字符当成HTML语法符号来进行渲染加载。闭合标签为endautoescape 。 注:为了安全考虑,一个字符串需要确认安全可信任后才能关闭自动转义。
示例:使用autoescape 关闭了自动转义功能后,加载出来直接就是一个超链接了。
context = {
'info': "<a href='www.baidu.com'>百度</a>"
}
{% autoescape off %}
{{ info }}
{% endautoescape %}
verbatim标签
在DTL模板中会自动解析{% %} 和{{ }} 等字符,如果某段代码你不想DTL去解析,就想它按照原内容输出,就可以使用verbatim 标签将这部分代码包裹起来。闭合标签为endverbatim 。
三、模板过滤器
过滤器其实就相当于一个可以接收参数的函数,对传入模板的某些值进行处理后显示。对于一个普通函数,如果直接通过render 将函数传入模板中,把它当成一个变量来使用,如果函数没有参数需要传递,则会直接将函数返回值渲染到模板中,如果这个函数需要参数,则无法这样使用了,此时可以考虑使用自定义过滤器来实现该函数的功能。 注:过滤器最多只能接收两个参数,使用形如{{ value|filter_name[:value2] }} 。
示例:将无参函数直接传入模板中
from django.shortcuts import render
def greet():
return 'hello world!'
def index(request):
context = {
'greet': greet
}
return render(request,context=context)
# 直接在模板中这样写:{{ greet }}
# 会将greet函数的返回值添加到模板中
内置模板过滤器
这里列举一些Django内置的常用过滤器,更多过滤器可以去官网看看。
-
add :使用形如{{ value|add:arg }} ,会尝试将value 和后面的参数先转换为int 类型再相加,如果失败,则会将两个参数直接进行+ 运算(字符串拼接和列表拼接),如果再次失败,则返回一个空字符串。
-
cut :使用形如{{ value|cut:arg }} ,移除字符串value 中指定的子串arg ,相当于Python中的value.replace(arg,'') 。
-
date :使用形如{{ my_date|date: "Y-m-d" }} ,将传入模板的日期对象如from datetime import datetime;my_date = datetime.now() 根据后面的格式字符串进行格式化。常用的格式字符如下:
格式字符 |
描述 |
Y |
四位数字的年份 |
m |
月份,如01-12 |
n |
月份,如1-12 |
d |
天,如01-31 |
j |
天,如1-31 |
h |
小时,12小时制,如01-12 |
g |
小时,12小时制,如1-12 |
H |
小时,24小时制,如01-24 |
G |
小时,24小时制,如1-24 |
i |
分钟,如00-59 |
s |
秒,如00-59 |
-
default :使用形如{{ value|default:arg }} ,如果value 在Python的if 判断中被判断为False 的话,如None 、空列表、空字符串、空字典等,则使用default 指定的值arg 。
-
default_if_none :使用形如{{ value|default:arg }} ,如果value 的值为None 则使用default 指定的值arg 。
-
fist :使用形如{{ value|first }} ,返回列表、元组、字符串的第一个元素。
-
last :使用形如{{ value|last }} ,返回列表、元组、字符串的最后一个元素。
-
floatformat :使用形如{{ value|floatformat }} 或者{{ value|floatformat:num }} ,格式化数字value 的输出(四舍五入),参数num 表示输出的小数位数,如果没有指定num (前者),则默认输出一位小数,需要注意,默认的情况下(前者),如果数字value 的小数部分原本就全为0,则不会输出对应的小数,只会输出为整数。
-
join :使用形如{{ value|join:"/" }} ,于Python中的join 方法类似,将列表或元组或字符串使用指定的字符拼接起来。
-
length :使用形如{{ value|length }} ,获取列表、元组、字符串、字典等的长度。
-
lower :使用形如{{ value|lower }} ,将value 中的字母全部转换为小写。
-
upper :使用形如{{ value|upper }} ,将value 中的字母全部转换为大写。
-
random :使用形如{{ value|random }} ,在给定的列表、元组、字符串中随机选择一个值。
-
safe :使用形如{{ value|safe }} ,表示给定的字符串value 是安全的,会关闭该字符串的自动转义,相当于{% autoescape off %} {{ value }} {% endautoescape %} ,即如果value 中包含了html接去执行这部分代码。
-
slice :使用形如{{ value|slice:"2:" }} ,相当于Python中的切片操作,Python中怎么切片,这里就怎么用,比如步长也是支持的,如{{ value|slice:"2::2" }} 指定步长为2。
-
striptags :使用形如{{ value|stiptags }} ,删除字符串中的所有HTML标签。
-
truncatechars :使用形如{{ value|truncatechars:num }} ,只显示字符串的前num-3 个字符串,之所以要减3,是因为num 表示要显示的字符串总长度,而最后输出的字符串后面会有三个点... 就占了3个字符了。
-
truncatechars_html :使用形如{{ value|truncatechars_html:num }} ,功能和truncatechars 类似,不同之处在于,truncatechars 会切割value 中的所有内容,而truncatechars_html 会忽略value 中的HTML标签。
自定义模板过滤器
模板过滤器其实就是一个普通的函数,自定义过滤器注意事项和步骤如下:
- 在子app目录下新建一个
templatetags 包,注意,这个包名只能是这个名称,不能随便进行自定义,不然Django无法识别。
- 在
templatetags 包下新建一个Python文件,文件名可以自定义,如my_filter.py ,然后在文件中进行过滤器的定义和注册。函数(过滤器)定义时,第一个参数必须是竖线左侧的值value ,如果过滤器需要参数,可以定义第二个参数,注意,过滤器最多只能有两个参数。示例代码如下:
"""my_filter.py"""
from django import template
register = template.Library()
# 定义过滤器,可以只有一个参数value,也可以定义两个参数,第二个参数可以设置默认值
# 注册方式一:以装饰器的方式进行注册,过滤器名称默认和函数名一样,
# 也可以通过参数指定过滤器名称
# @register.filter('my_greet')
@register.filter
def greet(value,word=''):
return value+word
# 注册方式二:以方法的方式进行注册,可以自定义过滤器名称
# register.filter('greet',greet)
- 将子app添加到
settings.py 中的配置项INSTALLED_APPS 。
- 在模板中使用自定义过滤器时,需要先在模板开头添加如
{% load my_filter %} ,注意,这里的my_filter 为包含过滤器的Python文件。示例代码如下:
{% load my_filter %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ value|greet:" 你好!" }}
</body>
</html>
四、特殊标签
include标签
使用形如{% include "xxx.html" [with var=value] %} ,相当于是把xxx.html 文件中的内容直接插入到指定位置(这个标签使用时的位置),with 表示定义一个参数,此参数可以在xxx.html 文件中引用。
对于父模板(使用include 标签的模板)中的参数,子模板(xxx.html )可以直接使用,如果父模板中没有此参数,就需要使用with 来定义该参数,不然子模板无法使用父模板中没有的参数了。
xxx.html 的路径表示也是相对于templates 文件夹的位置。
extends标签
extends 标签必须写在HTML代码的最前面一行,否则会报错。
使用形如{% extends "xxx.html" %} ,可以将xxx.html 中所有的内容继承到当前文件中,父模板(xxx.html )中使用形如{% block block_name %}...{% endblock %} 来定义一个“块”,子模板(当前模板)如果想要重写这个block 中的内容,直接在子模板中重写这个block 即可,子模板中的相同block 名称的block 内容会覆盖父模板中同名的block ,如果不想覆盖父模板中此block 的内容,又想在此父block 中添加一些新内容,可以使用{{ block.super }} 引用父模板中此block 的所有内容。
如果模板使用了extends 标签,而子模板中的内容没有写在block 块中,那么在block 之外的代码就会被忽略(无效代码),所以子模板中的内容都必须要先在父模板中使用block 进行占位,再在子模板中进行重写。 注:传入子模板中的变量是可以直接在父模板中使用的。
五、静态文件加载
静态文件的加载可以使用全路径名,即相对于项目根目录的路径名,但是在DTL模板中也可以使用static 标签,感兴趣可以看下,以下是使用方法和注意事项:
- 因为
static 标签并不是Django内置的标签,所以每次使用时都需要先{% load static %} ,为了解决这个问题,可以在settings.py 中的TEMPLATES 的OPTIONS 字典中添加'builtins': ['django.templatetags.static'] ,这样static 标签就可以像Django内置标签一样直接使用了。
- 确保
django.contrib.staticfiles 已经被添加到settings.py 中的配置项INSTALLED_APPS 中了。(默认是已经添加了的)
- 确保在
settings.py 中配置了STATIC_URL 配置项,此配置项用于设置静态文件的自动查找路径,默认为/static/ 。(默认已经配置了的)
- 将对应子app添加到
settings.py 中的配置项INSTALLED_APPS 中,并在子app目录下创建static 文件夹。
- 使用形如
<img src="{% static 'logo.jpg' %}" alt=""> 访问某个静态文件,此静态文件路径是相对于子app下的static 文件夹的相对路径。
- 如果需要放置一些整个项目都通用的静态文件(通常都需要),也可以在项目根目录下创建一个
static 文件夹,然后在settings.py 文件中配置STATICFILES_DIRS 配置项(列表)中将这个static 文件夹的路径添加进去即可(可以参考模板templates 文件夹的配置方法)。如此的话,Django在各个子app下都查找不到对应的静态文件的话,就会在这个目录下去查找。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|