自定義template過濾器的方法參考文檔,不再贅述
is_safe
文檔說明過濾的兩種最終形態(tài),其中一種是設(shè)置register.filter(is_safe=True)
,但是對is_safe的具體作用說的云山霧繞的,而查了些博文只是簡單的說is_safe可以關(guān)閉掉自動轉(zhuǎn)義(這個說法是錯誤的!)
我嘗試了加或者不加is_safe的效果
@register.filter
def demo(value):
return '<br>' + value
@register.filter(is_safe=True)
def demo(value):
return '<br>' + value
<li> {{ text|demo}} </li>
結(jié)果就是都對過濾器返回的結(jié)果進(jìn)行了轉(zhuǎn)義!
后來發(fā)現(xiàn)重點(diǎn)在于文檔中的這一句話:
This flag tells Django that if a “safe” string is passed into your filter, the result will still be “safe” and if a non-safe string is passed in, Django will automatically escape it, if necessary.
這個標(biāo)志告訴Django 如果"安全"的字符串傳遞到您的過濾,結(jié)果仍將是"安全",如果一個非安全字符串傳遞柠硕,如果必要Django 會自動轉(zhuǎn)義它扒寄。
重點(diǎn)在于"安全",也就是文檔中提到的SafeData
類型.文檔中有提到'某些正常的字符串操作會將SafeData對象轉(zhuǎn)換成普通的str或unicode對象,Django的過濾器在完成之后會修復(fù)這種破壞,并且很困難'.
這才是is_safe的意義所在:如果傳入的value已經(jīng)是SafeData對象,is_safe會告訴Django當(dāng)前過濾器輸出的數(shù)據(jù)不再需要轉(zhuǎn)義.
至于SafeData類型數(shù)據(jù)的來源,我暫時只知道mark_safe()
函數(shù)會返回SafeData對象.
from django.utils.safestring import mark_safe
@register.filter()
def to_safe(value):
return mark_safe(value)
@register.filter(is_safe=True)
def demo(value):
return '<br>' + value
<li> {{ test|to_safe|demo }} </li>
這樣的情況,demo過濾器接收到一個SafeData對象,其結(jié)果不會再轉(zhuǎn)義(<br>換行符起作用了).
need_autoescape
如果在注冊過濾器時添加了need_autoescape=True
,那么過濾器必須接收一個autoescape
參數(shù),這樣過濾器會捕捉其引用位置的自動轉(zhuǎn)義是否開啟,以決定你在過濾器中的行為.
引用下文檔中的栗子:
@register.filter(needs_autoescape=True)
def initial_letter_filter(text, autoescape=True):
first, other = text[0], text[1:]
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
result = '<strong>%s</strong>%s' % (esc(first), esc(other))
return mark_safe(result)
該過濾器的輸出通過mark_safe()
函數(shù)標(biāo)記為"安全",這樣可以保證在過濾器中引入的HTML標(biāo)簽可以實(shí)現(xiàn).但是同樣要考慮輸入的安全問題.如果模板中autoescape
是開啟的,說明我們已經(jīng)認(rèn)定這部分的數(shù)據(jù)是存在威脅的,所以需要在過濾器中手動對輸入數(shù)據(jù)進(jìn)行轉(zhuǎn)義來保證其安全性.