django模板,自定义标签和filter
注:这悲催的缩进,真是对不起观众了,有时间过来修改。
自定义标签大致分为三类:
1、非封闭标签如{% current_time "%Y-%m-%d %I:%M %p" %}
2、封闭标签如{%upper%}{%endupper%}
3、inclusion标签 比如{% books_for_author author %}
定义一个标签需要做两方面工作:1、定义编译函数 2、定义node。
编译函数的作用是将自定义node中的render所需要的参数计算出来,以备使用。比如将自定义tag中的参数等分离出来,或是将封闭标签中的nodelist算出来。自定义node的目的是提供该标签的render函数,将结果返回,或者存放在context中
非封闭标签
以定义{% current_time "%Y-%m-%d %I:%M %p" %}为例
1)定义编译函数:
from django import template
register = template.Library()
@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])
2)定义node
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)
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 ''
另外一个非封闭标签中比较常用、比较复杂的一个例子
自定义tag:{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
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)
封闭标签,
以{%upper%}{%endupper%}为例
def do_upper(parser, token):
"""
将两个标签之间的node保存到nodelist,然后传入UpperNode类供处理
"""
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
"""
调用nodelist中node的render()方法,然后将返回的内容保存在output中,最后对output做大写操作
"""
def render(self, context):
output = self.nodelist.render(context)
return output.upper()
inclusion 标签
inclusion tag,该tag需要一个模板配合它。比如{% books_for_author author %}
只需要两方面工作,一是定义一个函数,以自定义标签的参数(本例中的author)函数的形参,返回值作为模板文件的输入参数(本例中的{'books': books})。二是定义一个模板
tag文件
@register.inclusion_tag('book_snippet.html')
def books_for_author(author):
books = Book.objects.filter(authors__id=author.id)
return {'books': books}
模板文件:
book_snippet.html
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
自定义filter
from django import template
register = template.Library()
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
使用方法: {{ somevariable|cut:" " }}
这里的somevariable便是cut中的value,“ ”便是arg,整个filter的作用是将somevariable中的“ ”(空格)替换成'',也即去掉somevariable中的空格