欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-13 10:39:20
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 %} 

好了,大功告成!