现在的位置: 首页 > 综合 > 正文

django中自定义过滤器,自定义标签

2014年01月01日 ⁄ 综合 ⁄ 共 4311字 ⁄ 字号 评论关闭

django模板中自带了一系列标签,有<if>,<ifequal>,<ifnotequal>,<for>等,但有时也不能满足需求,比方说我要判断一个对象是否在一个集合中,就没有实现这个功能的现成标签。要实现这个功能,有两种方式,一种是自定义过滤器,一种是自定义标签:

自定义过滤器比较简单:

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

使用场景:用户登录的时候判断当前用户的权限,如果是超级管理员,则可以查看所有用户的信息,并添加用户等,如果只是普通的用户,则只能看到自己的信息:

自定义过滤器引用方式:

{% 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>标签源码如下:

@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>标签后,代码如下:

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)

引用方式:

{% 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 %}

好了,大功告成!

 

 

 

 

 

 

 

 

抱歉!评论已关闭.