1. 程式人生 > >Django第十篇-----關於模板的高階話題---下半篇

Django第十篇-----關於模板的高階話題---下半篇

目錄

自定義模板標籤和過濾器

自定義模板過濾器

過濾器的定義:

註冊自定義的過濾器

自定義模板標籤

引入標籤


自定義模板標籤和過濾器

Django 的模板語言自帶了豐富的標籤和過濾器,能滿足常見的表現邏輯需求。但是,這些內建的標籤和過濾器可能缺少你需要的功能。
我們可以擴充套件模板引擎,使用 Python 自定義標籤和過濾器,然後使用 {% load %} 標籤載入,讓自定義的標籤和過濾器可在模板中使用。

自定義模板過濾器

自定義的過濾器其實就是普通的 Python 函式,接受一個或多個引數:

1. 變數的值(輸入),不一定是字串。
2. 引數的值,可以有預設值,也可以留空。

例如,對 {{ var|foo:"bar" }} 來說,傳給 foo 過濾器的變數是 var ,引數是 "bar" 。因為模板語言沒有提供異常處理功能,所以模板過濾器丟擲的異常會以伺服器錯誤體現出來。

過濾器的定義:

def cut(value, arg):
    """Removes all values of arg from the given string"""
    return value.replace(arg, '')

這個過濾器的用法舉例如下:

{{ somevariable|cut:"0" }}

多數過濾器沒有引數。此時,在函式中留空引數即可。例如:

def lower(value): # 只有一個引數
    """Converts a string into all lowercase"""
    return value.lower()

註冊自定義的過濾器

定義好過濾器之後,要使用 Library 例項註冊,讓 Django 的模板語言知道它的存在:

register.filter('cut', cut)
register.filter('lower', lower)

Library.filter() 有兩個引數:

1. 過濾器的名稱,一個字串。
2. 負責處理過濾器的函式,一個 Python 函式(不是函式名稱的字串形式)。

register.filter() 也可以作為裝飾器使用:

@register.filter(name='cut')
def cut(value, arg):
    return value.replace(arg, '')
@register.filter
def lower(value):
    return value.lower()

自定義模板標籤

標籤能做任何事情,比過濾器複雜。Django 提供了一些快捷方式,簡化了多數標籤型別的編寫。首先,我們將探討這些快捷方式,然後說明在快捷方式不夠用時如何從頭開始編寫標籤。

例如有個 current_time 標籤,它接受一個格式字串,返回格式化後的時間字串

據此, current_time 函式可以這麼編寫:

import datetime
from django import template
register = template.Library()
@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

如果模板標籤需要訪問當前上下文,註冊標籤時指定 takes_context 引數:

@register.simple_tag(takes_context=True)
def current_time(context, format_string):
    timezone = context['timezone']
    return your_get_current_time_method(timezone, format_string)

如果想為標籤起個別的名稱,指定 name 引數:

register.simple_tag(lambda x: x - 1, name='minusone')
@register.simple_tag(name='minustwo')
def some_function(value):
    return value - 2

使用 simple_tag 裝飾的函式可以接受任意個位置引數和關鍵字引數。例如:

@register.simple_tag
def my_tag(a, b, *args, **kwargs):
    warning = kwargs['warning']
    profile = kwargs['profile']
    ...
    return ...

然後在模板中可以把任意個引數(以空格分開)傳給這個標籤。與 Python 程式碼一樣,關鍵字引數的值使用等號( = )設定,而且必須放在位置引數後面。例如:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

引入標籤

首先,要定義一個接受引數的函式,生成一個字典,為結果提供資料。注意,我們只需返回一個字典,而不是其他複雜的資料結構。返回的字典在模板片段的上下文中使用。

def books_for_author(author):
    books = Book.objects.filter(authors__id=author.id)
    return {'books': books}

Author 物件名下的圖書列表。我們將像這樣使用這個標籤:

{% books_for_author author %}

得到的結果如下:

<ul>
    <li>The Cat In The Hat</li>
    <li>Hop On Pop</li>
    <li>Green Eggs And Ham</li>
</ul>

然後,建立用於渲染標籤輸出的模板。對這個標籤來說,模板十分簡單:

<ul>
{% for book in books %}
    <li>{{ book.title }}</li>
{% endfor %}
</ul