自定義 Django 模板標(biāo)簽和過濾器
雖然 Django 已經(jīng)給我們提供了足夠豐富的內(nèi)置標(biāo)簽和過濾器,但實際開發(fā)中還是會遇到內(nèi)置標(biāo)簽和過濾器無法滿足的需求,此時 Django 還給我們提供了實現(xiàn)自定義模板標(biāo)簽和過濾器的方式。想要自定義模板標(biāo)簽和過濾器,必須按照如下的方式做好前面的準(zhǔn)備工作。
我們在前面的第一個應(yīng)用 (hello_app) 中添加自定義的標(biāo)簽和模板。首先完成如下兩步:
- 必須新建一個名為 templatetags 的目錄。注意,這個名稱固定,不能取其他名稱。這個文件夾與該應(yīng)用目錄下的
models.py
、views.py
同級; - 該目錄下要有一個
__init__.py
文件,此外還要新建一個用于定義標(biāo)簽和過濾器的文件:hello_extras.py
。
整個應(yīng)用目錄如下:
(django-manual) [root@server first_django_app]# tree hello_app/
hello_app/
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── templatetags
│ ├── hello_extras.py
│ └── __init__.py
├── tests.py
├── urls.py
└── views.py
1. 自定義 Django 模板過濾器
首先,我們完成一個簡單的 sum 過濾器,這個 sum 過濾器的作用是將輸入的數(shù)組中的元素相加,用法示例如下:
{{ value|sum }}
假設(shè)輸入的 value 值為 [1, 2, 3 ,4, 5],那么輸出結(jié)果為15。Django 中并沒有提供 sum 過濾器,我們需要自己首先這樣一個 sum 過濾器。首先在hello_extras.py
文件中添加如下代碼:
from django import template
register = template.Library()
@register.filter(name="sum")
def sum(value):
if isinstance(value, list):
try:
sum = 0
for i in range(len(value)):
sum += int(value[i])
return sum
except Exception as e:
return 0
return value
首先是準(zhǔn)備好過濾器函數(shù) sum(),然后使用 register.filter()
注冊該過濾器函數(shù),這樣我們自定義的 sum 過濾器就算完成了。接下來準(zhǔn)備模板文件,在 template 目錄下新建測試的模板文件,如下:
(django-manual) [root@server templates]# cat test_custom_filter.html
{% load hello_extras %}
{{ value|sum }}
注意:第一步必須使用 load 標(biāo)簽導(dǎo)入我們自定義的過濾器模塊,然后才能使用自定義的過濾器。
(django-manual) [root@server first_django_app]# python manage.py shell
Python 3.8.1 (default, Dec 24 2019, 17:04:00)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template.loader import get_template
>>> tp = get_template('test_custom_filter.html')
>>> content = tp.render(context={'value': [1, 2, 3, 4, 5]})
>>> print(content)
15
可以看到,我們已經(jīng)成功實現(xiàn)了 sum 過濾器。
2. 自定義 Django 模板標(biāo)簽
自定義標(biāo)簽可以幫助我們做更多的事情,Django 幫助開發(fā)者在自定義模板標(biāo)簽上提供了一些快捷方式,使得開發(fā)者能夠快速開發(fā)出各種自定義的標(biāo)簽,極大提升開發(fā)效率。 simple_tag()
方法就是其中的快捷方式之一。這個函數(shù)是django.template.Library
的一個方法。
假設(shè)我們想實現(xiàn)一個模板標(biāo)簽,顯示當(dāng)前的時間。我們在前面的 hello_extras.py
中添加如下模板標(biāo)簽代碼:
import datetime
from django import template
register = template.Library()
@register.simple_tag
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
這里標(biāo)簽 current_time 可以帶上一個參數(shù),用于指定顯示時間的格式。該標(biāo)簽的使用方式如下:
{% load hello_extras %}
{% current_time "%Y-%m-%d %H:%M:%S" as the_time %}
<p>The time is {{ the_time }}.</p>
我們繼續(xù)使用 Django 的 shell 功能測試該模板標(biāo)簽:
(django-manual) [root@server first_django_app]# python manage.py shell
Python 3.8.1 (default, Dec 24 2019, 17:04:00)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template.loader import get_template
>>> tp = get_template('test_custom_filter.html')
>>> content = tp.render(context={})
>>> print(content)
<p>The time is 2020-03-30 13:46:07.</p>
可以看到,我們自定義的模板標(biāo)簽是生效了。除此之外,對于 simple_tag 自定義的標(biāo)簽還可以使用模板的上下文對象。例如:
@register.simple_tag(takes_context=True)
def current_time(context, format_string):
timezone = context['timezone']
# 調(diào)用自己的處理函數(shù)
return your_get_current_time_method(timezone, format_string)
注意:這里自定義標(biāo)簽方法的第一個參數(shù)必須是 context。
最后 simple_tag 還可以接收位置參數(shù)和關(guān)鍵字參數(shù),具體如下:
@register.simple_tag
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
# 忽略...
return ...
這樣的自定義模板標(biāo)簽使用示例如下:
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}
3. 小結(jié)
這里我們通過兩個簡單的實戰(zhàn)例子實現(xiàn)了自定義過濾器和自定義模板標(biāo)簽。至此,Django 的模板系統(tǒng)介紹可以正式告一段落了。接下來將學(xué)習(xí) Django 的模型層。