Login

ifinlist template tag

Author:
nomadjourney
Posted:
January 6, 2009
Language:
Python
Version:
1.0
Score:
0 (after 0 ratings)

I recently had to write a custom template tag which checks to see if a value exists in a list variable from within a Django template. This was my first ever attempt at writing a template tag so any feedback would be appreciated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
from django.template import Library, Node, NodeList, TemplateSyntaxError, Variable
from django.utils.translation import ugettext as _

register = Library()

class IfInListNode( Node ):
    """
    Implements the actual logic of the ifinlist tag.
    """
    def __init__( self, value_var, list_var, nodelist_true, nodelist_false ):
        self.value_var, self.list_var = Variable( value_var ), Variable( list_var )
        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false

    def __repr__( self ):
        return "<IfInListNode>"

    def render( self, context ):
        try:
            value_var = self.value_var.resolve( context )
        except VariableDoesNotExist:
            list_var = None
        
        try:
            list_var = self.list_var.resolve( context )
        except VariableDoesNotExist:
            list_var = None
        
        if not isinstance( list_var, list ):
            raise
            
        if value_var in list_var:
            return self.nodelist_true.render(context)
        
        return self.nodelist_false.render(context)

def do_ifinlist( parser, token ):
    """
    Checks if a value is in a list.
    
    Sample usage:
    
    Suppose that we have the following value and list variables passed to the template:

        letter = 'C'
        letters = [ 'A', 'B', 'C', 'D' ]
    
        {% ifinlist letter letters %}
            Yes
        {% else %}
            No
        {% endifinlist %}
    """
    bits = token.contents.split()
    len_bits = len( bits )
    
    if len_bits != 3:
        raise TemplateSyntaxError( _( '%s tag requires three arguments' ) % bits[ 0 ] )
    
    nodelist_true = parser.parse( ( 'else', 'endifinlist' ) )
    token = parser.next_token()
    
    if token.contents == 'else':
        nodelist_false = parser.parse( ( 'endifinlist', ) )
        parser.delete_first_token()
    else:
        nodelist_false = NodeList()

    return IfInListNode( bits[ 1 ], bits[ 2 ], nodelist_true, nodelist_false )

do_ifinlist = register.tag( 'ifinlist', do_ifinlist )

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 8 months ago

Comments

nomadjourney (on January 7, 2009):

Sweet. The filter approach is much simpler than using a custom tag. Awesome. Thanks for pointing it out!

#

Please login first before commenting.