过滤器从字面的意思上,可以理解为:过滤掉不需要的,剩下我们需要的,Django 的模板语言同样也内置了过滤器,如果你了解其他的框架对这个词一定不陌生,比如说 Flask 框架、Vue 框架等,都内置了过滤器这个功能,在本节我们将一起学习 Django 框架的过滤器。
过滤器作用是在变量输出时,对输出的变量值做进一步的处理。
比如,我们可以使用过滤器来更改变量的输出显示。
过滤器跟模板标签一样,也是在模板中对函数进行调用
比如,对输出的日期进行格式化处理,或者转换大小写字母等,这些都有对应的过滤器去处理它们。当内置过滤器满足不了需求的情况下,也可自定义过滤器。过滤器的语法格式如下:
{{ 变量 | 过滤器1:参数值1 | 过滤器2:参数值2 ... }}
从语法格式我们可以得知过滤器使用|
管道符进行变量与过滤器之间的连接,过滤器的可以通过组合多个过滤器实现链式调用,目前过滤器最多接受一个参数。经常使用的过滤器如下表所示:
常见的模板过滤器
过滤器 | 使用说明 |
---|---|
length | 获取变量的长度,适用于字符串和列表 |
lower/upper | 转换字符串为小写/大写形式 |
first/last | 获取变量的首个/末尾元素 |
add:‘n’ | 给变量值增加 n |
safe | 默认不对变量内的字符串进行html转义 |
cut | 从给定的字符串中删除指定的值 |
dictsort | 获取字典列表,并返回按参数中给定键排序的列表 |
join | 用字符串连接列表,例如 Python 的 str.join(list) |
truncatewords | 如果字符串字符多于指定的字符数量,那么会被截断。 截断的字符串将以可翻译的省略号序列(“…”)结尾 |
过滤器相比模板标签要简单的多,我们可以把它们理解成一个 Python 函数,传递参数给他处理就可以了,当滤器接收参数后对它进行处理,最终将处理结果返回到模板中,这就是整个过滤器的实现流程,下面我们通过一些具体的实例,来更加详细理解它的使用方法。
我们使用 length 过滤器得到变量的长度:
# 数据
{'world':'乔治'}
# 过滤器
<p>hello:{{world|length}}</p>
在一定数量的单词后截断字符串,语法格式如下所示:
# 数据
{'value':'Django is website'}
# 过滤器
<p>{{ value|truncatewords:2 }}</p>
dictsort 它指定字典的键为参数,最后返回按照指定键排序的列表,它的用法如下所示:
# 数据
{'value':[
{'name': 'C语言', 'num':2 },
{'name': 'Django官网', 'num': 1},
{'name': 'Python官网', 'num': 3},
]}
# 过滤器
<p>hello:{{value|dictsort:"num"}}</p>
从输出的结果可以看出 dictsort 过滤器对指定的键 num 做了排序处理。
当然过滤器也可以与模板标签配合使用,这种属于综合的使用方法,实例如下:
# 数据
{'books':[
{'title': 'C语言', 'author': {'name': 'ycs', 'age': 14}},
{'title': 'Python教程', 'author': {'name': 'xxw', 'age': 17}},
{'title': 'Django教程', 'author': {'name': 'ccs', 'age': 16}},
]}
# 过滤器
{% for book in books|dictsort:"author.age" %}
<p>{{ book.title }} ({{ book.author.name }})</p>
{% endfor %}
add 过滤的用法也非常的简单,变量值是整型而且参数也是整型,此时的 add 过滤器相当于加法运算,但是如果变量值和参数都是列表又会怎么样呢,让我们通过下面的例子来看一下:
# 数据
{'value':'5'}
# 过滤器
{{ value|add:2 }}
# 数据
{'value':['python','Django','Flask'],'list':['Tonado','celery']}
# 过滤器
{{value|add:list}}
add 过滤器将首先尝试将两个值都强制转换为整数。如果失败,它将尝试将所有值加在一起。这将对某些数据类型(如字符串,列表等)起作用,而对其他数据类型则失败。如果失败,结果将为空字符串。
在 Django 的模板语言中除了我们前面章节介绍过的 if 标签和 for 标签之外,还有许多我们时常用到标签。
比如 url 标签。
Django 的模板语言为我们提供了 url 标签,url 标签可以避免在模板中使用硬编码的方式插入要访问的 url 地址。
所谓硬编码就是将数据直接嵌入到程序或其他可执行对象的源代码中,比如我们修改了视图的访问地址,如果模板中采用的是硬编码的话,那么也需要对模板中的访问地址 url 进行修改,让它们保持数据的一致,但是这样对于采用 MTV 设计模式的 Django 框架来说是极其不方便的。
url 标签就很好的避免了这一点,它的使用语法格式如下:
{% url 'url_name' args1 args2 %}
我们解析一下它的的含义,其中 app_name 代表我们创建的应用的名字此处是 index;url_name 是 url 自定义的别名,可以在配置路由地址时通过 path 的 name 属进行设置。而后面的 args1、args2 参数是用于定义动态的 url 即带有查询的字符串的 url。下面我们通过已经讲过的实例代码对 url 标签进行讲解。
总路由:
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', include('index.urls')),
]
首先我们在urls.py文件中为url设置别名,如下所示:(子路由)
urlpatterns = [
path('Hello_MyWeb/', views.Hello_MyWeb, name='hello'),
path('test_url/', views.test_url)
]
然后我们在 templates 目录下创建一个名为 test_url 的 html 文件,添加一下代码:
<p><a href="{% url 'hello' %}" >点我查看django课程a>p>
最后我们在 views.py 文件中创建一个 test_url 函数,如下所示:
def test_url(request):
return render(request, 'test_url.html')
在浏览器地址栏访问 127.0.0.1:8000/index/test_url/ ,通过点击可以跳转到 Hello_MyWeb 页面。如果你想跳转到其他的页面,只需要将给相应路由配置 name 属性即可,而我们无需做其他的改动。name 参数有非常重要作用,url 的反向解析也是通过它与reverse()
函数配合使用实现的。这个知识点后续还会讲到。
如果是带参数的 url 我们要怎么处理它呢?
其实通过简单一段代码我们就能够明白,下面我们对前述代码进行改写。
首更改 path 路由函数映射关系,如下所示:
path('Hello_MyWeb/' , views.Hello_MyWeb, name='hello')
改动 Hello_MyWeb 视图函数,为其添加 id 参数,如下所示:
def Hello_MyWeb(request, id):
再把模板中的标签改写成如下格式:
<p><a href="{% url 'hello' 1 %}" >点我查看django课程a>p>
通过访问 127.0.0.1/index/test_url 地址,可以得到如下显示结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xs5J4J4N-1681956145195)(imgs\企业微信截图_20230419155559.png)]
我们点击上述链接会跳转到 Hello_MyWeb 视图的页面,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xk6V91af-1681956145197)(imgs\企业微信截图_20230419155709.png)]
通过前面几节的内容,我们对 Django 内置的模板标签与过滤器做了深入的探讨学习。
Django 虽然内置了二十多种标签和六十多种过滤器,但是为了给 Web 开发者提供更好使用体验,Django 也提供了自定义标签与过滤器的功能。当内置标签与过滤器满足不了实际业务的需求,那么我们就可以通过自定义的方式去实现,在本节我们将对如何实现自定义标签进行讲解。
自定义标签可以分为三种类型:简单标签(simple_tag)、引用标签(inclusion_tag)、赋值标签(assignment_tag),在本节我们对它们进行详细的描述。
Django 为我们提供了自定义的机制,我们可以通过使用 Python 代码来自定义标签来,最后使用{% load %}
标签进行加载。但是在自定义标签之前,需要我们做一些准备工作,如下所示:
__init__.py
文件;[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlFHmjQz-1681956145198)(imgs\企业微信截图_20230419161054.png)]
给 index_tags.py 文件命名时,需要注意不能与 Django 内置的标签或者过滤器名字冲突,如同 Python 中命名不可以使用关键字一样,所以我们在命名时应该尽量使用带有下划线的命名方式,这样可以确保名字不冲突。
上述操作完成后,我们就可以使用 {% load index_tags %} 加载自定义标签了, loda 标签将加载指定的的自定义标签,但是在 templatetags 目录中自定义标签或者过滤器的数量是没有限制的,你可以根据自己实际需求进行构建。
要在模块内自定义标签,该模块必须包含一个名为 register 的模板层变量,且它的值是 template.Library 的实例,所有的标签和过滤器都是在其中注册的。
所以我们需要打开 index_tags.py 文件,并在文件顶部加上如下代码:
from django import template
register = template.Library()
简单标签通过接收参数,对输入的参数做一些处理并返回结果。
如下所示,在 index_tags .py 文件中定义 addstr_tag 标签:
#注册自定义简单标签
@register.simple_tag
def addstr_tag(strs):
return 'Hello%s' % strs
addstr_tag 函数使用 register.simple_tag 进行装饰,目的是能够将 addstr_tag 注册到模板系统中。
然后我们就可以使用 {% load %} 加载自定义的标签了,使用如下方式:
{% load index_tags %}
加载之后我们就可以使用我们的自定义标签了,通过举例看一下实际的效果:
我们直接在test_url.html尝试:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<p><a href="{% url 'hello' 1 %}" >点我查看django课程a>p>
<p>
{% load index_tags %}
{% addstr_tag 'Django BookStore' %}
p>
body>
html>
效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B0VebrPH-1681956145199)(imgs\企业微信截图_20230419172535.png)]
这个标签类似于简单标签,使用 register.simple_tag 进行注册,但它并不会直接输出结果,而是使用 as 关键字将结果储存在指定的上下文变量中,从而降低了传输上下文的成本。
下面在 index_tags.py 中定义test_as_tag 标签,如下所示:
#注册自定义赋值标签
@register.simple_tag
def test_as_tag(strs):
return 'Hello Test Tag-%s'%strs
使用自定义赋值标签,实例如下所示:
我们直接在test_url.html尝试:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<p><a href="{% url 'hello' 1 %}" >点我查看django课程a>p>
{% load index_tags %}
{% test_as_tag 'django课堂欢迎你' as test %}
<p>{{ test }}p>
body>
html>
效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swbqGKjN-1681956145199)(imgs\企业微信截图_20230419191758.png)]
自定义标签看似简单,但需要我们灵活的掌握它们,使用最合适的方式,最适用的逻辑让复杂的问题变得简单化。这是一个慢慢锻炼的过程,而理解了它最基本的使用方法,是漫漫征程中的第一步。
url ‘hello’ 1 %}" >点我查看django课程
{{ test }}
```效果如下:
[外链图片转存中…(img-swbqGKjN-1681956145199)]
自定义标签看似简单,但需要我们灵活的掌握它们,使用最合适的方式,最适用的逻辑让复杂的问题变得简单化。这是一个慢慢锻炼的过程,而理解了它最基本的使用方法,是漫漫征程中的第一步。