Package omeroweb :: Package webadmin :: Package templatetags :: Module conditional_tags
[hide private]
[frames] | no frames]

Source Code for Module omeroweb.webadmin.templatetags.conditional_tags

  1  #!/usr/bin/env python 
  2  #  
  3  #  
  4   
  5  """ 
  6  source: http://djangosnippets.org/snippets/1350/ 
  7   
  8  A smarter {% if %} tag for django templates. 
  9   
 10  While retaining current Django functionality, it also handles equality, 
 11  greater than and less than operators. Some common case examples:: 
 12   
 13      {% if articles|length >= 5 %}...{% endif %} 
 14      {% if "ifnotequal tag" != "beautiful" %}...{% endif %} 
 15  """ 
 16   
 17  import traceback 
 18  import logging 
 19   
 20  from django import template 
 21   
 22  register = template.Library() 
 23   
 24  logger = logging.getLogger('conditional_tags') 
25 26 -class BaseCalc(object):
27
28 - def __init__(self, var1, var2=None, negate=False):
29 self.var1 = var1 30 self.var2 = var2 31 self.negate = negate
32
33 - def resolve(self, context):
34 try: 35 var1, var2 = self.resolve_vars(context) 36 outcome = self.calculate(var1, var2) 37 except: 38 outcome = False 39 if self.negate: 40 return not outcome 41 return outcome
42
43 - def resolve_vars(self, context):
44 var2 = self.var2 and self.var2.resolve(context) 45 return self.var1.resolve(context), var2
46
47 - def calculate(self, var1, var2):
48 raise NotImplementedError()
49
50 51 -class Or(BaseCalc):
52 - def calculate(self, var1, var2):
53 return var1 or var2
54
55 56 -class And(BaseCalc):
57 - def calculate(self, var1, var2):
58 return var1 and var2
59
60 61 -class Equals(BaseCalc):
62 - def calculate(self, var1, var2):
63 return var1 == var2
64
65 66 -class Greater(BaseCalc):
67 - def calculate(self, var1, var2):
68 return var1 > var2
69
70 71 -class GreaterOrEqual(BaseCalc):
72 - def calculate(self, var1, var2):
73 return var1 >= var2
74
75 76 -class In(BaseCalc):
77 - def calculate(self, var1, var2):
78 return var1 in var2
79 80 81 82 OPERATORS = { 83 '=': (Equals, True), 84 '==': (Equals, True), 85 '!=': (Equals, False), 86 '>': (Greater, True), 87 '>=': (GreaterOrEqual, True), 88 '<=': (Greater, False), 89 '<': (GreaterOrEqual, False), 90 'or': (Or, True), 91 'and': (And, True), 92 'in': (In, True), 93 } 94 BOOL_OPERATORS = ('or', 'and')
95 96 97 -class IfParser(object):
98
99 - def __init__(self, tokens):
100 self.tokens = tokens 101 self.error_class = ValueError
102
103 - def _get_tokens(self):
104 return self._tokens
105
106 - def _set_tokens(self, tokens):
107 self._tokens = tokens 108 self.len = len(tokens) 109 self.pos = 0
110 111 tokens = property(_get_tokens, _set_tokens) 112
113 - def parse(self):
114 if self.at_end(): 115 raise self.error_class('No variables provided.') 116 var1 = self.get_bool_var() 117 while not self.at_end(): 118 op, negate = self.get_operator() 119 var2 = self.get_bool_var() 120 var1 = op(var1, var2, negate=negate) 121 return var1
122
123 - def get_token(self, eof_message=None, lookahead=False):
124 negate = True 125 token = None 126 pos = self.pos 127 while token is None or token == 'not': 128 if pos >= self.len: 129 if eof_message is None: 130 raise self.error_class() 131 raise self.error_class(eof_message) 132 token = self.tokens[pos] 133 negate = not negate 134 pos += 1 135 if not lookahead: 136 self.pos = pos 137 return token, negate
138
139 - def at_end(self):
140 return self.pos >= self.len
141
142 - def create_var(self, value):
143 return TestVar(value)
144
145 - def get_bool_var(self):
146 var = self.get_var() 147 if not self.at_end(): 148 op_token = self.get_token(lookahead=True)[0] 149 if isinstance(op_token, basestring) and (op_token not in 150 BOOL_OPERATORS): 151 op, negate = self.get_operator() 152 return op(var, self.get_var(), negate=negate) 153 return var
154
155 - def get_var(self):
156 token, negate = self.get_token('Reached end of statement, still ' 157 'expecting a variable.') 158 if isinstance(token, basestring) and token in OPERATORS: 159 raise self.error_class('Expected variable, got operator (%s).' % 160 token) 161 var = self.create_var(token) 162 if negate: 163 return Or(var, negate=True) 164 return var
165
166 - def get_operator(self):
167 token, negate = self.get_token('Reached end of statement, still ' 168 'expecting an operator.') 169 if not isinstance(token, basestring) or token not in OPERATORS: 170 raise self.error_class('%s is not a valid operator.' % token) 171 if self.at_end(): 172 raise self.error_class('No variable provided after "%s".' % token) 173 op, true = OPERATORS[token] 174 if not true: 175 negate = not negate 176 return op, negate
177
178 -class TemplateIfParser(IfParser):
179 error_class = template.TemplateSyntaxError 180
181 - def __init__(self, parser, *args, **kwargs):
182 self.template_parser = parser 183 return super(TemplateIfParser, self).__init__(*args, **kwargs)
184
185 - def create_var(self, value):
186 return self.template_parser.compile_filter(value)
187
188 189 -class SmartIfNode(template.Node):
190 - def __init__(self, var, nodelist_true, nodelist_false=None):
191 self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false 192 self.var = var
193
194 - def render(self, context):
195 if self.var.resolve(context): 196 return self.nodelist_true.render(context) 197 if self.nodelist_false: 198 return self.nodelist_false.render(context) 199 return ''
200
201 - def __repr__(self):
202 return "<Smart If node>"
203
204 - def __iter__(self):
205 for node in self.nodelist_true: 206 yield node 207 if self.nodelist_false: 208 for node in self.nodelist_false: 209 yield node
210
211 - def get_nodes_by_type(self, nodetype):
212 nodes = [] 213 if isinstance(self, nodetype): 214 nodes.append(self) 215 nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) 216 if self.nodelist_false: 217 nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) 218 return nodes
219 220 @register.tag('if')
221 -def smart_if(parser, token):
222 bits = token.split_contents()[1:] 223 var = TemplateIfParser(parser, bits).parse() 224 nodelist_true = parser.parse(('else', 'endif')) 225 token = parser.next_token() 226 if token.contents == 'else': 227 nodelist_false = parser.parse(('endif',)) 228 parser.delete_first_token() 229 else: 230 nodelist_false = None 231 return SmartIfNode(var, nodelist_true, nodelist_false)
232
233 234 #============================================================================== 235 # Tests 236 #============================================================================== 237 238 -class TestVar(object):
239 """ 240 A basic self-resolvable object similar to a Django template variable. Used 241 to assist with tests. 242 """
243 - def __init__(self, value):
244 self.value = value
245
246 - def resolve(self, context):
247 return self.value
248