程式語言:Python
Package:Django
Django 官網文件
簡介:自定義 Tags & Filter
範例
範例
範例
例:一個能夠產生指定作者對象的書籍清單的標籤。結果如下
有時候,包含標籤需要訪問父模板的 context。
可使用 takes_context 選項。注意函數的第一個參數必須是 context。
例:一個包含標籤,該標籤包含有指向主頁的 home_link 和 home_title 變量
Package:Django
Django 官網文件
簡介:自定義 Tags & Filter
初步設置
- 在 APP 下建立 templatetags 資料夾
- 資料夾下建立 __init__.py,並建立 mine.py (可自行命名)
- 在 template html 中,加入 {% load mine%}
- 在 mine.py 頂端加入
from django import template register = template.Library()
自定義 template filters
可定義參數- 輸入變數的值
- 參數的值,可以是默認值或者完全留空
# template html {{ somevariable|cut:"0" }} # in mine.py #register.filter('cut', cut) @register.filter(name='cut') def cut(value, arg): """Removes all values of arg from the given string""" return value.replace(arg, '')
# template html {{ somevariable|lower}} # in mine.py #register.filter('lower', lower) @register.filter def lower(value): # Only one argument. """Converts a string into all lowercase""" return value.lower()
自定義 template tags
當 Django 編譯一個模板時- 將原始模板分成一個個 節點。
- 每個節點都是 django.template.Node 的一個實例,並且具備 render() 方法。
範例
# template html <p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p> # in mine.py from django import template register = template.Library() import datetime class CurrentTimeNode(template.Node): def __init__(self, format_string): self.format_string = str(format_string) def render(self, context): now = datetime.datetime.now() return now.strftime(self.format_string) #register.tag('current_time', do_current_time) @register.tag(name="current_time") def do_current_time(parser, token): try: # split_contents() knows not to split quoted strings. tag_name, format_string = token.split_contents() except ValueError: msg = '%r tag requires a single argument' % token.split_contents()[0] raise template.TemplateSyntaxError(msg) return CurrentTimeNode(format_string[1:-1])
- 每個標籤編譯函數有兩個參數,parser 和 token。
- parser是模板解析器對象。此例無使用。可看後面的例子
- token是被解析的語句。
- token.contents 是包含有標籤原始內容的字符串。
- 此例為 'current_time "%Y-%m-%d %I:%M %p"' 。
- token.split_contents() 按空格拆分,並保證引號中的字串不拆分。
- 避免使用 token.contents.split(),因可能會拆分字串中的空白
- 可拋出 django.template.TemplateSyntaxError
- 提供所有語法錯誤的有用信息。
- token.split_contents()[0] 記錄標籤的名字,就算標籤沒有任何參數。此例為 current_time
- 返回一個 CurrentTimeNode ,包含了節點需要知道的關於這個標籤的全部信息。
- 此例只傳遞了參數 "%Y-%m-%d %I:%M %p"。
- 雙引號使用 format_string[1:-1] 去除。
- 模板標籤編譯函數必須返回一個 Node 子類,返回其它值都是錯的。
# template html {% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %} <p>The current time is {{ my_current_time }}.</p> # in mine.py import re class CurrentTimeNode3(template.Node): def __init__(self, format_string, var_name): self.format_string = str(format_string) self.var_name = var_name def render(self, context): now = datetime.datetime.now() context[self.var_name] = now.strftime(self.format_string) return '' def do_current_time(parser, token): # This version uses a regular expression to parse tag contents. try: # Splitting by None == splitting by spaces. tag_name, arg = token.contents.split(None, 1) except ValueError: msg = '%r tag requires arguments' % token.contents[0] raise template.TemplateSyntaxError(msg) m = re.search(r'(.*?) as (\w+)', arg) if m: fmt, var_name = m.groups() else: msg = '%r tag had invalid arguments' % tag_name raise template.TemplateSyntaxError(msg) if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")): msg = "%r tag's argument should be in quotes" % tag_name raise template.TemplateSyntaxError(msg) return CurrentTimeNode3(fmt[1:-1], var_name)
block tag
範例# template html {% upper %} This will appear in uppercase, {{ user_name }}. {% endupper %} # in mine.py def do_upper(parser, token): nodelist = parser.parse(('endupper',)) parser.delete_first_token() return UpperNode(nodelist) class UpperNode(template.Node): def __init__(self, nodelist): self.nodelist = nodelist def render(self, context): output = self.nodelist.render(context) return output.upper()
- parser.parse() 的參數為 tuple,內含需要分析的模板標籤名
- 返回一個 django.template.NodeList 實例
- 包含了所有 Node 對象的列表
- 解析器在 tuple 指定的標籤之前遇到的內容
- nodelist 不包括開始跟結束標籤,此例為 {% upper %} 和 {% endupper %}。
- parser.parse() 被調用後,分析器並無清除 {% endcomment %} 標籤,因此需要調用 parser.delete_first_token() 來防止該標籤被處理兩次。
- 更多的範例可看 django/template/defaulttags.py
Simple tags
- 傳遞給函數只有單個參數。
- 函數被調用時,檢查必需參數個數的工作已經完成,無需再做這個工作。
- 參數兩邊的引號(如果有的話)已被截掉,只會接收到一個普通字符串。
範例
import datetime from django import template register = template.Library() #{% current_time1 "%Y-%m-%d %I:%M %p" %} @register.simple_tag def current_time1(format_string): return datetime.datetime.now().strftime(format_string) #{% current_time2 "%Y-%m-%d %I:%M %p" %} @register.simple_tag(takes_context=True) def current_time2(context, format_string): timezone = context['timezone'] return your_get_current_time_method(timezone, format_string) #{% minusone 2 %} => 1 register.simple_tag(lambda x: x - 1, name='minusone') #{% minustwo 2 %} => 0 @register.simple_tag(name='minustwo') def some_function(value): return value - 2 #{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %} @register.simple_tag def my_tag(a, b, *args, **kwargs): warning = kwargs['warning'] profile = kwargs['profile'] ... return ... #{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %} #<p>The time is {{ the_time }}.</p>
Inclusion tags
通過渲染 其他 template 顯示數據範例
例:一個能夠產生指定作者對象的書籍清單的標籤。結果如下
- The Cat In The Hat
- Hop On Pop
- Green Eggs And Ham
# template html {% books_for_author author %} # in mine.py #register.inclusion_tag('book_snippet.html')(books_for_author) @register.inclusion_tag('book_snippet.html') def books_for_author(author): books = Book.objects.filter(authors__id=author.id) return {'books': books} # in book_snippet.html <ul> {% for book in books %} <li>{{ book.title }}</li> {% endfor %} </ul>
有時候,包含標籤需要訪問父模板的 context。
可使用 takes_context 選項。注意函數的第一個參數必須是 context。
例:一個包含標籤,該標籤包含有指向主頁的 home_link 和 home_title 變量
# template html {% jump_link %} # in mine.py @register.inclusion_tag('link.html', takes_context=True) def jump_link(context): return { 'link': context['home_link'], 'title': context['home_title'], } # in link.html Jump directly to <a href="{{ link }}">{{ title }}</a>.
留言
張貼留言