django中自定义过滤器,自定义标签
django模板中自带了一系列标签,有<if>,<ifequal>,<ifnotequal>,<for>等,但有时也不能满足需求,比方说我要判断一个对象是否在一个集合中,就没有实现这个功能的现成标签。要实现这个功能,有两种方式,一种是自定义过滤器,一种是自定义标签:
自定义过滤器比较简单:
[python]
import datetime
from django import template
from django.template.base import (node, nodelist, templatesyntaxerror)
register = template.library()
@register.filter(name='authorityfilter')
def authorityfilter(value, authority_list):
for authority in authority_list:
if authority == value:
return true
return false
使用场景:用户登录的时候判断当前用户的权限,如果是超级管理员,则可以查看所有用户的信息,并添加用户等,如果只是普通的用户,则只能看到自己的信息:
自定义过滤器引用方式:
[python]
{% load common_tags %}
{% if 'accountsuperuser'|authorityfilter:request.session.authority_list_button %}
<li><a href="{% url accounts_index %}" target="navtab" rel="accountindex" title="用户管理">用户管理</a></li>
{% else %}
<li><a href="{% url accounts_info user.id %}" target="navtab" rel="accountindex" title="用户信息">用户信息</a></li>
{% endif %}
自定义标签比较复杂,在这里学到一种学习方法,因为django框架是开源的,所以安装好后直接可以看到它的。我想判断一个对象是否在一个集合中,要定义的这个标签跟django自带的<ifequal>这个标签实现的功能很类似,好了,先把这个<ifequal>这个标签的源码找出来研究一下。<ifequal>标签源码如下:
[python
@register.tag
def ifequal(parser, token):
"""
outputs the contents of the block if the two arguments equal each other.
examples::
{% ifequal user.id comment.user_id %}
...
{% endifequal %}
{% ifnotequal user.id comment.user_id %}
...
{% else %}
...
{% endifnotequal %}
"""
return do_ifequal(parser, token, false)
@register.tag
def ifnotequal(parser, token):
"""
outputs the contents of the block if the two arguments are not equal.
see ifequal.
"""
return do_ifequal(parser, token, true)
def do_ifequal(parser, token, negate):
bits = list(token.split_contents())
if len(bits) != 3:
raise templatesyntaxerror("%r takes two arguments" % bits[0])
end_tag = 'end' + bits[0]
nodelist_true = parser.parse(('else', end_tag))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse((end_tag,))
parser.delete_first_token()
else:
nodelist_false = nodelist()
val1 = parser.compile_filter(bits[1])
val2 = parser.compile_filter(bits[2])
return ifequalnode(val1, val2, nodelist_true, nodelist_false, negate)
class ifequalnode(node):
child_nodelists = ('nodelist_true', 'nodelist_false')
def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
self.var1, self.var2 = var1, var2
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self.negate = negate
def __repr__(self):
return "<ifequalnode>"
def render(self, context):
val1 = self.var1.resolve(context, true)
val2 = self.var2.resolve(context, true)
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
return self.nodelist_true.render(context)
return self.nodelist_false.render(context)
改成<ifcontain>标签后,代码如下:
[python]
def iscontain(obj, obj_list):
for tmpobj in obj_list:
if tmpobj == obj:
return true
return false
class ifcontainnode(node):
child_nodelists = ('nodelist_true', 'nodelist_false')
def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
self.var1, self.var2 = var1, var2
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self.negate = negate
def __repr__(self):
return "<ifcontainnode>"
def render(self, context):
val1 = self.var1.resolve(context, true)
val2 = self.var2.resolve(context, true)
if (self.negate and not iscontain(val1, val2)) or (not self.negate and iscontain(val1, val2)):
return self.nodelist_true.render(context)
return self.nodelist_false.render(context)
def do_ifcontain(parser, token, negate):
bits = list(token.split_contents())
if len(bits) != 3:
raise templatesyntaxerror("%r takes two arguments" % bits[0])
end_tag = 'end' + bits[0]
nodelist_true = parser.parse(('else', end_tag))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse((end_tag,))
parser.delete_first_token()
else:
nodelist_false = nodelist()
val1 = parser.compile_filter(bits[1])
val2 = parser.compile_filter(bits[2])
return ifcontainnode(val1, val2, nodelist_true, nodelist_false, negate)
@register.tag
def ifcontain(parser, token):
"""
outputs the contents of the block if the second argument contain the first argument.
examples::
{% ifcontain user userlist %}
...
{% endifcontain %}
{% ifnotcontain user userlist %}
...
{% else %}
...
{% endifnotcontain %}
"""
return do_ifcontain(parser, token, false)
@register.tag
def ifnotcontain(parser, token):
"""
outputs the contents of the block if the second argument not contain the first argument.
see ifcontain.
"""
return do_ifcontain(parser, token, true)
引用方式:
[python]
{% load common_tags %}
{% ifcontain 'accountsuperuser' request.session.authority_list_button %}
<li><a href="{% url accounts_index %}" target="navtab" rel="accountindex" title="用户管理">用户管理</a></li>
{% else %}
<li><a href="{% url accounts_info user.id %}" target="navtab" rel="accountindex" title="用户信息">用户信息</a></li>
{% endifcontain %}
好了,大功告成!