知識點(diǎn):
- 代碼布局
- 編寫自定義模板過濾器
- 簡單標(biāo)簽
- 包含標(biāo)簽
- 分配標(biāo)簽
- 靜態(tài)文件加載
為了解決應(yīng)用中展示邏輯的需求,Django的模板語言提供了各式各樣的built-in tags and filters。 然而,你或許會發(fā)現(xiàn)模板內(nèi)建的這些工具集合不一定能全部滿足你的功能需要。 您可以通過使用Python定義自定義標(biāo)簽和過濾器來擴(kuò)展模板引擎,然后使用{% load %}標(biāo)簽。
代碼布局
指定自定義模板標(biāo)簽和過濾器的最常見的地方在Django應(yīng)用程序中。
當(dāng)將Django應(yīng)用程序添加到INSTALLED_APPS中時(shí),在下面描述的常規(guī)位置中定義的任何標(biāo)簽將自動在模板中加載。
這個(gè)應(yīng)用應(yīng)該包含一個(gè)templatetags 目錄,和views.py、models.py等文件處于同一級別目錄下。 如果目錄不存在則創(chuàng)建它——不要忘記創(chuàng)建init.py 文件以使得該目錄可以作為Python 的包。
你的自定義的標(biāo)簽和過濾器將放在templatetags 目錄下的一個(gè)模塊里。 這個(gè)模塊的名字是你稍后將要載入標(biāo)簽時(shí)使用的,所以要謹(jǐn)慎的選擇名字以防與其他應(yīng)用下的自定義標(biāo)簽和過濾器名字沖突。
例如,你的自定義標(biāo)簽/過濾器在一個(gè)名為common_extras.py的文件中,那么你的app目錄結(jié)構(gòu)看起來應(yīng)該是這樣的:
common/
__init__.py
models.py
templatetags/
__init__.py
common_extras.py
views.py
在模板中像如下這樣使用:
{% load common_extras %}
為了讓{% load %}標(biāo)簽工作,包含自定義標(biāo)簽的應(yīng)用必須在INSTALLED_APPS中。在 templatetags 包中放多少個(gè)模塊沒有限制。 只需要記住{% load %} 聲明將會載入給定模塊名中的標(biāo)簽/過濾器,而不是應(yīng)用的名稱。
為了成為一個(gè)可用的標(biāo)簽庫,這個(gè)模塊必須包含一個(gè)名為 register的變量,它是template.Library 的一個(gè)實(shí)例,所有的標(biāo)簽和過濾器都是在其中注冊的。 所以把如下的內(nèi)容放在你的模塊的頂部:
from django import template
register = template.Library()
編寫自定義模板過濾器
自定義過濾器就是一個(gè)帶有一個(gè)或兩個(gè)參數(shù)的Python 函數(shù):
- (輸入的)變量的值 —— 不一定是字符串形式。
- 參數(shù)的值 —— 可以有一個(gè)初始值,或者完全不要這個(gè)參數(shù)。
例如,在{{ var|foo:"bar" }}中,foo過濾器應(yīng)當(dāng)傳入變量var和參數(shù) "bar"。
定義過濾器的例子:
def mycut(value, arg):
return value.replace(arg, '')
這個(gè)過濾器的使用:
{{ somevariable|mycut:"0" }}
大多數(shù)過濾器沒有參數(shù)。 在這種情況下,你的函數(shù)不帶這個(gè)參數(shù)即可。 例如:
def mylower(value):
return value.lower()
注冊自定義過濾器
django.template.Library.filter()
讓自定義的過濾器在Django模板語言中可用,就需要把它注冊為你的 Library實(shí)例:
register.filter('mycut', mycut)
register.filter('mylower', mylower)
Library.filter()方法需要兩個(gè)參數(shù):
- 過濾器的名稱(一個(gè)字符串對象)
- 編譯的函數(shù) – 一個(gè)Python函數(shù)(不要把函數(shù)名寫成字符串)
還可以把register.filter()用作裝飾器:
@register.filter(name='mycut')
def mycut(value, arg):
return value.replace(arg, '')
@register.filter
def mylower(value):
return value.lower()
沒有聲明 name 參數(shù),Django將使用函數(shù)名作為過濾器的名字。
如果你正在編寫一個(gè)只希望用一個(gè)字符串來作為第一個(gè)參數(shù)的模板過濾器,你應(yīng)當(dāng)使用stringfilter裝飾器。 這將在對象被傳入你的函數(shù)之前把這個(gè)對象轉(zhuǎn)換成它的字符串值:
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter #注釋掉此句傳遞int類型會報(bào)錯(cuò)
def mylower(value):
return value.lower()
編寫自定義模板標(biāo)簽
簡單標(biāo)簽django.template.Library.simple_tag()
許多模板標(biāo)簽需要許多參數(shù) - 字符串或模板變量,并且僅在基于輸入?yún)?shù)和一些外部信息進(jìn)行一些處理后返回結(jié)果。 例如,current_time 標(biāo)簽可能接受一個(gè)格式字符串,并返回與之對應(yīng)的格式化后的時(shí)間。
為了簡單化這些類型標(biāo)簽的創(chuàng)建,Django 提供一個(gè)輔助函數(shù)simple_tag。 這個(gè)函數(shù)是django.template.Library 的一個(gè)方法,接受一個(gè)任意數(shù)目的參數(shù)的函數(shù),將其包裝在一個(gè)render 函數(shù)和上面提到的其他必要部分中,并在模板系統(tǒng)中注冊它。
注冊標(biāo)簽,向模塊的Library實(shí)例注冊代碼
register.tag('current_time', do_current_time)
tag()方法有兩個(gè)參數(shù):
- 模板標(biāo)記的名稱 - 字符串。 如果省略,將使用編譯函數(shù)的名稱。
- 編譯的函數(shù) – 一個(gè)Python函數(shù)(不要把函數(shù)名寫成字符串)
與過濾器注冊一樣,也可以將其用作裝飾器。
例子:
# hello_django/music/templatetages/common_tag.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)
如果你的模板標(biāo)簽需要訪問當(dāng)前上下文,你可以在注冊標(biāo)簽時(shí)使用takes_context 參數(shù)︰
# hello_django/music/templatetages/common_tag.py
@register.simple_tag(takes_context=True)
def current_time(context ):
tm = context['format_string']
return datetime.datetime.now().strftime(tm)
# 這里的tm是從視圖函數(shù)context中傳進(jìn)來的。
包含標(biāo)簽django.template.Library.inclusion_tag()
另一種常見類型的模板標(biāo)簽是通過渲染另外一個(gè)模板來顯示一些數(shù)據(jù)。這些類型的標(biāo)簽被稱為"Inclusion 標(biāo)簽"。
例子:
# hello_django/music/templatetages/common_tag.py
@register.inclusion_tag('music/show_tag.html')
def show_results():
li = ['python','java','c++']
return {'choices':li}
{# hello_django/music/templates/show_tag.html#}
<ul>
{% for i in choices %}
<li>{{ i }}</li>
{% endfor %}
</ul>
分配標(biāo)簽
為了簡單化設(shè)置上下文中變量的標(biāo)簽的創(chuàng)建,Django 提供一個(gè)輔助函數(shù)assignment_tag。 除了將標(biāo)簽的結(jié)果存儲在指定的上下文變量中,而不是直接輸出,該函數(shù)的工作方式與simple_tag()相同。
我們之前的current_time 函數(shù)從而可以這樣寫︰
# hello_django/music/templatetages/common_tag
@register.assignment_tag
def current_time_1(format_string):
return datetime.datetime.now().strftime(format_string)
然后你可以使用as 參數(shù)后面跟隨變量的名稱將結(jié)果存儲在模板變量中,并將它輸出到你覺得合適的地方︰
{% current_time_1 '%Y-%m-%d %H:%M:%P' as ctime %}
The time is {{ ctime }}
模板加載靜態(tài)文件
1、在settings中,找到INSTALLED_APPS,然后確保有django.contrib.staticfiles。
2、在settings中,選擇性的設(shè)置STATIC_ROOT和STATIC_URL以及STATICFILES_DIRS
3、STATICFILES_DIRS可以設(shè)置絕對路徑也可以是相對路徑。同templates
4、默認(rèn)STATICFILES_FINDERS會到安裝了的app下面的static文件夾找靜態(tài)文件。
5、在模板中,使用static標(biāo)簽加載靜態(tài)文件。注意路徑!
例子:
我們在app下面創(chuàng)建一個(gè)static的目錄,在目錄中添加三種靜態(tài)文件:
# hello_djagngo/music/static/myjs.js
alert('hahahaha');
# --------------------------------
# hello_djagngo/music/static/mystyle.css
body{
background: skyblue;
}
#---------------------------------
# hello_djagngo/music/static/myimage.jpg
##存入圖片
靜態(tài)文件創(chuàng)建好了之后就可以在模板里面加載靜態(tài)文件。
{# hello_django/music/templates/index.html#}
<link rel="stylesheet" href="{% static 'mystyle.css' %}">
<script src="{% static 'myjs.js' %}"></script>
圖片:
<img src="{% static 'myimage.jpg' %}" alt=""/>