django支援自定義標籤和過濾器。起初還不太重視它這項功能,但最近試了試自定義標籤。發現django這個功能實在是太爽了。
再如果是在templatetags資料夾中定義了標籤,如 test_tags.py,要如何使用我們自定義的test_tags.py呢。很簡單,只要在django的模板中加入,在test_tags.py 原始檔中的自定義標籤就可以在有load語句的模板中使用了。
下面詳細的來談談建立自定義標籤的過程以及方法。
一定記得要在templatetags資料夾中包含__init__.py檔案。空檔案便可。
2.編寫自定義檔案**test_tags.py。
現看看簡單一點的過濾器(filter).
我的乙個簡單**如下
python**
#!/usr/bin/env python
#coding:utf-8
from django import template
register = template.library()
def percent_decimal(value):
value = float(str(value))
value = round(value, 3)
value = value * 100
return str(value) + '%'
register.filter('percent_decimal', percent_decimal)
以上**的意思是將傳過來的小數轉換成百分比顯示。(django自帶乙個widthratio標籤頁可以完成此問題,但它的誤差太大,小數字直接截掉了)。
其中register = template.library(),register.filter('percent_decimal', percent_decimal) 兩句是將所寫**註冊到能用標籤。最後一句的register.filter('percent_decimal', percent_decimal) 。第乙個引數是字串,就只在模板中使用時候的字串比如},名字可以自由取得。後面乙個引數接受乙個函式名,這個便是上面自定義的percent_decimal方法了。此方法中的value引數便是從模板中傳遞過來的引數。比如}, percent_decimal方法接受到的value引數便是
12.09.
再來看看如何自定義tags。
自定義tags相對自定義filter要複雜一點。但仔細研究的話難度也不大。
自定義tags最基本的格式如下
python**
from django import template
register = template.library()
class testnode(template.node):
def __init__(self):
pass
def render(self, context):
return
"***xx"
def test(parser, token):
return testnode()
register.tag('my_tag', test)
其中包的引入和註冊跟filter型別。主要的功能**是乙個類(繼承自template.node,所有的自定義tags都必須從這個類繼承)和乙個方法,以上**什麼功能都沒有做,但我們要先搞明白它的實現機制。
如果從模板中使用以上的自定義tags,比如,則會呼叫上面**註冊的test方法,其中test方法中有兩個引數,乙個是parser,這個作用是挺大的,稍後說明。另乙個是token,這個便是從模板當中使用的這個標籤中所包含的所有字串。如果使用的是}則,token的值為「my_tag aaa.bbb」。注意是字串型別。
隨後呼叫testnode類,當中有個render方法,其中有個引數是context,這個context引數就是在執行模板的渲染時由 view 傳入的,在這裡跟在被渲染的模板中可以呼叫同樣的變數,可以試驗在render中列印 "print user",便顯示的是登陸使用者的資訊。
大概明白了自定義tags的實現機制後。看乙個複雜一點點的**。
python**
class permissionlevel(template.node):
"""根據級別返回相應值
"""def __init__(self, sequence, text_level):
self.sequence = sequence
self.text_level = text_level
pass
def render(self, context):
userinfo = context['user']
level = 4
#拿到使用者級別
values = self.sequence.resolve(context, true)
ifself.text_level <= level:
return str(values)
else:
return
'***'
def do_permission_level(parser, token):
try:
tag_name, text_name, text_level = token.split_contents()
except:
raise template.templatesyntaxerror, \
"%r 標籤語法錯誤,後面引數為兩位,分別為變數名和該變數資訊隱私等級" % \
token.split_contents[0]
try:
text_level = int(text_level)
except:
raise templatesyntaxerror, "permission_level標籤語法錯誤,資訊隱私等級應為整型數字"
sequence = parser.compile_filter(text_name)
return permissionlevel(sequence, text_level)
register.tag('permission_level', do_permission_level)
以上的**完成的功能是判定乙個資訊的隱私級別,再根據登陸使用者的許可權來區分顯示或不顯示。在模板中的用法如下
其中permission_level 為標籤名,objects.count是從view中傳遞過來的變數或屬性。後面的 4 便是此屬性(objects.count)的隱私級別為4,只有登入使用者隱私級別大於它的時候才會顯示,否則顯示為「***」。
下面仔細來分析一下上面的**。
tag_name, text_name, text_level = token.split_contents()
這一句將分解成三個字元,其中text_name為「objects.count 」。這裡跟自定義的filter不同,filter 是可以接受非字元的引數的,型別}也可以是},後面的2引數加了引號。其中如果不加引號的話便傳遞的是非字元物件,像模板中的user是可以通過filter傳遞過去的。但tags不同,tag傳遞給註冊的函式中的引數是字串。
當時想到做自定義的tags也是專案需要。但自己開始做的時候發現tag傳遞的是字串,當時也查了不少資料沒找到解決的方法,那時就想放棄自定義tags了。但注意到django自帶的tags不也是傳遞字元嗎,像, 這樣的,django肯定有什麼方法可以將類似「user」, "test_list"這樣的字元和view中傳遞來的物件關聯起來。於是便開始硬著頭皮看django的原始碼了。(要知道對於像我這樣的菜鳥來說。看原始碼可不是容易的事情)。
到底django是用什麼魔法做到字元變物件的呢。起先我以為是這樣的,比如,則先提取user取來,再將傳遞過去的user從context中取去,user=context['user'],但後來一想,單個的物件好想是可以,但如果有句點符號的是怎麼做到的呢。就像user.username?難道是再將它通過字串操作再分離一次,但如果遇到多個句點符號呢?類似
user.profile.realname。照這個思路看原始碼,發現不是我想的這樣的。有些源**沒看太懂,但正是這些沒看懂的**才是關鍵。
再回頭看看上面的**,註冊標籤的**方法中有個parser引數,正是這個引數。
對照上面的**。
sequence = parser.compile_filter(text_name)
將開始從token.split_contents()中分離出來的 像:user,,user.age , user.profile.realname等字串先編譯成乙個sequence 物件。怎麼編譯的我也不太明白,不去管它了。
隨後在類方法裡面有句values = self.sequence.resolve(context, true)
再列印出values來看看,type(values)看看,哈哈。不再是字串了,是真正的例項物件或是變數。
那麼一切ok。雖然不知道django中這兩句是怎麼樣實現的,但不管了。至少現在我們可以自由的定製適合的filter和tags了。
Django自定義過濾器和標籤
django的模板語言包含了各種各樣的內建標籤和過濾器來滿足你的應用需求,不過有時候你也會發現你的需要的功能不在內建的功能中,這時候你可以通過python語言自定義標籤和過濾器來擴充套件模板引擎,然後在你的模板中使用來載入使用它們。首先建立好包檔案 init py templatetags init...
Django 自定義標籤和過濾器
from django import template from django.utils.safestring import mark safe register template.library register的名字是固定的,不可改變 register.filter name myfilter...
Django自定義過濾器和自定義標籤
3 在模板下建立任意名稱的.py檔案 4 在剛剛建立的.py檔案中定製過濾器 from django.template import library register library register.filter name rule 最多包含兩個引數 defrule value,before 將b...