python_django_customTemplate

Custom template tags and filters

Django’s template language comes with a wide variety of built-in tags and filters designed to address the presentation logic needs of your application. Nevertheless, you may find yourself needing functionality that is not covered by the core set of template primitives. You can extend the template engine by defining custom tags and filters using Python, and then make them available to your templates using the {%load %} tag.

Django的模板語言帶有各種內置標記和過濾器,旨在滿足應用程序的表示邏輯需求。然而,您可能會發現自己需要的功能並沒有被核心模板原語集所覆蓋。您可以通過使用python定義自定義標記和過濾器來擴展模板引擎,然後使用%load%標記將它們提供給模板。

 

Code layout

Django的模板語言帶有各種內置標記和過濾器,旨在滿足應用程序的表示邏輯需求。然而,您可能會發現自己需要的功能並沒有被核心模板原語集所覆蓋。您可以通過使用python定義自定義標記和過濾器來擴展模板引擎,然後使用%load%標記將它們提供給模板。

 

Development server won’t automatically restart

After adding the templatetags module, you will need to restart your server before you can use the tags or filters in templates.

 

您的自定義標記和過濾器將位於templateTags目錄內的模塊中。模塊文件的名稱是稍後加載標記時使用的名稱,因此請小心選擇一個不會與其他應用程序中的自定義標記和篩選器衝突的名稱。

例如,如果自定義標記/過濾器位於名爲poll_extras.py的文件中,則應用程序佈局可能如下所示:

polls/
    __init__.py
    models.py
    templatetags/
        __init__.py
        poll_extras.py
    views.py

 

And in your template you would use the following:

{% load poll_extras %}

包含自定義標記的應用程序必須位於已安裝的應用程序中,以便 {% load %} 來使用,這是一個安全特性:它允許您在一臺主機上爲許多模板庫託管python代碼,而不允許在每次Django安裝時訪問所有模板庫。

在templateTags包中放入的模塊數量沒有限制。 {% load %}語句將爲給定的python模塊名加載標記/過濾器,而不是應用程序名。

要成爲有效的標記庫,模塊必須包含一個名爲register的模塊級變量,該變量是一個template.library實例,其中註冊了所有標記和篩選器。因此,在模塊頂部附近,放置以下內容:

from django import template

register = template.Library()

New in Django 1.9.

模板標記模塊可以通過“libraries”參數註冊到djangotemplates。如果要在加載模板標記時使用與模板標記模塊名稱不同的標籤,則此選項非常有用。它還允許您在不安裝應用程序的情況下注冊標記。

 

 


 

Writing custom template filters

自定義過濾器只是採用一個或兩個參數的python函數:

  • 變量(輸入)的值-不一定是字符串。
  • 參數的值——可以有一個默認值,也可以完全忽略。

例如,在過濾器{{ 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): # Only one argument.
    """Converts a string into all lowercase"""
    return value.lower()

 

Registering custom filters

django.template.Library.filter()

編寫完過濾器定義後,需要將其註冊到庫實例中,以使其可用於Django的模板語言:

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

The Library.filter() method takes two arguments:

  1. The name of the filter – a string.
  2. The compilation function – a Python function (not the name of the function as a string).

You can use register.filter() as a decorator instead:

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

@register.filter
def lower(value):
    return value.lower()

如果不使用name參數,如上面的第二個示例中所示,Django將使用函數的名稱作爲過濾器名稱。

最後,register.filter()還接受三個關鍵字參數,是安全的,需要自動轉義,並期望本地時間。這些參數在下面的過濾器和自動轉義以及過濾器和時區中描述。


Template filters that expect strings

django.template.defaultfilters.stringfilter()

If you’re writing a template filter that only expects a string as the first argument, you should use the decorator stringfilter. This will convert an object to its string value before being passed to your function

from django import template
from django.template.defaultfilters import stringfilter

register = template.Library()

@register.filter
@stringfilter
def lower(value):
    return value.lower()

這樣,您就可以將一個整數傳遞給這個過濾器,並且不會導致attributeError(因爲整數沒有lower()方法)。

Filters and time zones

如果您編寫一個對日期時間對象進行操作的自定義過濾器,那麼您通常會將其註冊爲expected\localtime標誌設置爲true。

@register.filter(expects_localtime=True)
def businesshours(value):
    try:
        return 9 <= value.hour < 17
    except AttributeError:
        return ''

 

設置此標誌後,如果篩選器的第一個參數是時區感知日期時間,Django將根據模板中時區轉換規則,在將其傳遞給篩選器之前將其轉換爲當前時區。


Writing custom template tags

標籤比過濾器更復雜,因爲標籤可以做任何事情。Django提供了許多快捷方式,使大多數類型的標記更容易編寫。首先,我們將研究這些快捷方式,然後解釋如何在快捷方式不夠強大時從頭開始爲這些情況編寫標記。

Simple tags

django.template.Library.simple_tag()

許多模板標記接受許多參數(字符串或模板變量),並在僅基於輸入參數和一些外部信息進行一些處理後返回結果。例如,當前的時間標記可能接受格式字符串,並將時間作爲相應格式的字符串返回。

爲了簡化這些類型標記的創建,Django提供了一個助手函數,即簡單的標記。此函數是django.template.library的一種方法,它接受一個接受任意數量參數的函數,將其包裝在一個呈現函數和上面提到的其他必要位中,並將其註冊到模板系統中。

因此,我們當前的時間函數可以這樣寫:

import datetime
from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

 

A few things to note about the simple_tag helper function

  • Checking for the required number of arguments, etc., has already been done by the time our function is called, so we don’t need to do that.
  • The quotes around the argument (if any) have already been stripped away, so we just receive a plain string.
  • If the argument was a template variable, our function is passed the current value of the variable, not the variable itself

 

If your template tag needs to access the current context, you can use the takes_context argument when registering your 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)

注意,第一個參數必須稱爲上下文。

有關takes-context選項如何工作的詳細信息,請參閱包含標記部分。

如果需要重命名標記,可以爲其提供自定義名稱。

 

register.simple_tag(lambda x: x - 1, name='minusone')

@register.simple_tag(name='minustwo')
def some_function(value):
    return value - 2

simple_tag functions 可以接受任意數量的位置或關鍵字參數。例如:

@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 %}

可以將標記結果存儲在模板變量中,而不是直接輸出它。這是通過使用as參數和變量名來完成的。這樣做可以讓您自己輸出您認爲合適的內容:

{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
<p>The time is {{ the_time }}.</p>

 

 

 

簡單實現 https://blog.csdn.net/qq_25046261/article/details/79577933

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章