15 自定義 Django 模板標籤和過濾器
雖然 Django 已經給我們提供了足夠豐富的內建標籤和過濾器,但實際開發中還是會遇到內建標籤和過濾器無法滿足的需求,此時 Django 還給我們提供了實現自定義模板標籤和過濾器的方式。想要自定義模板標籤和過濾器,必須按照如下的方式做好前面的準備工作。
我們在前面的第一個應用 (hello_app) 中新增自定義的標籤和模板。首先完成如下兩步:
- 必須新建一個名為 templatetags 的目錄。注意,這個名稱固定,不能取其他名稱。這個資料夾與該應用目錄下的
models.py
、views.py
同級; - 該目錄下要有一個
__init__.py
檔案,此外還要新建一個用於定義標籤和過濾器的檔案:hello_extras.py
整個應用目錄如下:
(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 過濾器的作用是將輸入的陣列中的元素相加,用法示例如下:
{{ value|sum }}
假設輸入的 value 值為 [1, 2, 3 ,4, 5],那麼輸出結果為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
首先是準備好過濾器函式 sum(),然後使用 register.filter()
註冊該過濾器函式,這樣我們自定義的 sum 過濾器就算完成了。接下來準備模板檔案,在 template 目錄下新建測試的模板檔案,如下:
(django-manual) [root@server templates]# cat test_custom_filter.html
{% load hello_extras %}
{{ value|sum }}
注意:第一步必須使用 load 標籤匯入我們自定義的過濾器模組,然後才能使用自定義的過濾器。
(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
可以看到,我們已經成功實現了 sum 過濾器。
2. 自定義 Django 模板標籤
自定義標籤可以幫助我們做更多的事情,Django 幫助開發者在自定義模板標籤上提供了一些快捷方式,使得開發者能夠快速開發出各種自定義的標籤,極大提升開發效率。 simple_tag()
方法就是其中的快捷方式之一。這個函式是django.template.Library
的一個方法。
假設我們想實現一個模板標籤,顯示當前的時間。我們在前面的 hello_extras.py
中新增如下模板標籤程式碼:
import datetime
from django import template
register = template.Library()
@register.simple_tag
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
這裡標籤 current_time 可以帶上一個引數,用於指定顯示時間的格式。該標籤的使用方式如下:
{% load hello_extras %}
{% current_time "%Y-%m-%d %H:%M:%S" as the_time %}
<p>The time is {{ the_time }}.</p>
我們繼續使用 Django 的 shell 功能測試該模板標籤:
(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>
可以看到,我們自定義的模板標籤是生效了。除此之外,對於 simple_tag 自定義的標籤還可以使用模板的上下文物件。例如:
@register.simple_tag(takes_context=True)
def current_time(context, format_string):
timezone = context['timezone']
# 呼叫自己的處理函式
return your_get_current_time_method(timezone, format_string)
注意:這裡自定義標籤方法的第一個引數必須是 context。
最後 simple_tag 還可以接收位置引數和關鍵字引數,具體如下:
@register.simple_tag
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
# 忽略...
return ...
這樣的自定義模板標籤使用示例如下:
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}
3. 小結
這裡我們通過兩個簡單的實戰例子實現了自定義過濾器和自定義模板標籤。至此,Django 的模板系統介紹可以正式告一段落了。接下來將學習 Django 的模型層。