Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get 'switch-case' statement functionality in Django templates?

I found a link to have a 'switch' tag in Django templates, but I was wondering if this can be somehow achieved without it. Using only the stuff which comes with Django? Basically is there other way then using multiple 'if' or 'ifequal' statements?

Thanks in advance for any tips/suggestions.

like image 939
Czlowiekwidmo Avatar asked Apr 07 '09 13:04

Czlowiekwidmo


People also ask

What does {% include %} do in Django?

From the documentation: {% extends variable %} uses the value of variable. If the variable evaluates to a string, Django will use that string as the name of the parent template. If the variable evaluates to a Template object, Django will use that object as the parent template.

What is Autoescape in Django?

autoescape. Controls the current auto-escaping behavior. This tag takes either on or off as an argument and that determines whether auto-escaping is in effect inside the block. The block is closed with an endautoescape ending tag.

What is Forloop counter in Django?

Django for loop counter All the variables related to the counter are listed below. forloop. counter: By using this, the iteration of the loop starts from index 1. forloop. counter0: By using this, the iteration of the loop starts from index 0.

Which option does Django templates accept?

DjangoTemplates engines accept the following OPTIONS : 'autoescape' : a boolean that controls whether HTML autoescaping is enabled. It defaults to True . Only set it to False if you're rendering non-HTML templates!


2 Answers

As of Django 1.4, there is {% elif %}:

{% if a %}   thing {% elif b %}   other thing {% elif c %}   another thing {% endif %}  
like image 152
Steve Bennett Avatar answered Sep 28 '22 04:09

Steve Bennett


To the previous responders: Without understanding the use case, you've made assumptions and criticized the questioner. @Ber says "all over the place" which is certainly not implied by the questioner. Not fair.

I have a case where I would like to do a {% switch %} statement in exactly one place in my Django template. Not only is it not convenient to move the equivalent of the switch statement into Python code, but that would actually make both the view and the template harder to read and take simple conditional logic that belongs in one place and split it into two places.

In many cases where I could imagine a {% switch %} (or an {% if %}) being useful, not using one requires putting HTML in a view. That's a far worse sin and is why {% if %} exists in the first place. {% switch %} is no different.

Fortunately, Django is extensible and multiple people have implemented switch. Check out:

Switch template tag

from django import template from django.template import Library, Node, VariableDoesNotExist  register = Library()   @register.tag(name="switch") def do_switch(parser, token):     """     The ``{% switch %}`` tag compares a variable against one or more values in     ``{% case %}`` tags, and outputs the contents of the matching block.  An     optional ``{% else %}`` tag sets off the default output if no matches     could be found::          {% switch result_count %}             {% case 0 %}                 There are no search results.             {% case 1 %}                 There is one search result.             {% else %}                 Jackpot! Your search found {{ result_count }} results.         {% endswitch %}      Each ``{% case %}`` tag can take multiple values to compare the variable     against::          {% switch username %}             {% case "Jim" "Bob" "Joe" %}                 Me old mate {{ username }}! How ya doin?             {% else %}                 Hello {{ username }}         {% endswitch %}     """     bits = token.contents.split()     tag_name = bits[0]     if len(bits) != 2:         raise template.TemplateSyntaxError("'%s' tag requires one argument" % tag_name)     variable = parser.compile_filter(bits[1])      class BlockTagList(object):         # This is a bit of a hack, as it embeds knowledge of the behaviour         # of Parser.parse() relating to the "parse_until" argument.         def __init__(self, *names):             self.names = set(names)         def __contains__(self, token_contents):             name = token_contents.split()[0]             return name in self.names      # Skip over everything before the first {% case %} tag     parser.parse(BlockTagList('case', 'endswitch'))      cases = []     token = parser.next_token()     got_case = False     got_else = False     while token.contents != 'endswitch':         nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch'))          if got_else:             raise template.TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name)          contents = token.contents.split()         token_name, token_args = contents[0], contents[1:]          if token_name == 'case':             tests = map(parser.compile_filter, token_args)             case = (tests, nodelist)             got_case = True         else:             # The {% else %} tag             case = (None, nodelist)             got_else = True         cases.append(case)         token = parser.next_token()      if not got_case:         raise template.TemplateSyntaxError("'%s' must have at least one 'case'." % tag_name)      return SwitchNode(variable, cases)  class SwitchNode(Node):     def __init__(self, variable, cases):         self.variable = variable         self.cases = cases      def __repr__(self):         return "<Switch node>"      def __iter__(self):         for tests, nodelist in self.cases:             for node in nodelist:                 yield node      def get_nodes_by_type(self, nodetype):         nodes = []         if isinstance(self, nodetype):             nodes.append(self)         for tests, nodelist in self.cases:             nodes.extend(nodelist.get_nodes_by_type(nodetype))         return nodes      def render(self, context):         try:             value_missing = False             value = self.variable.resolve(context, True)         except VariableDoesNotExist:             no_value = True             value_missing = None          for tests, nodelist in self.cases:             if tests is None:                 return nodelist.render(context)             elif not value_missing:                 for test in tests:                     test_value = test.resolve(context, True)                     if value == test_value:                         return nodelist.render(context)         else:             return "" 
like image 40
Roy Leban Avatar answered Sep 28 '22 04:09

Roy Leban