Nix
Nix

Reputation: 58572

Django Template - Stop processing template

I am looking for way to clean up a template in django. A simple solution would be to break this up into multiple templates, but we do not want to do that.

We basically have the following

{%if data.some_state %}
    Display some markup
{% else %}
   {%if data.some_state_2 %}
       State 2 different html view 
   {% else %}
        {%if data.process_data %}
           Display some list of data
        {% else %}
           No Data to display!
       {% endif %} <!-- if data.process_data-->
   {% endif %} <!-- if data.some_state_2 -->
{% endif %} <!-- if data.some_state -->

So that is extremely confusing and hard to read. If I could do this in a "function" i would use if/else if or returns.

Is there a way in template language to do something like (stop_processing_template would tell the template we are done... ):

{%if data.some_state %}
    Display some markup
{% endif %}
{% django_stop_processing_template %}


{%if data.some_state_2 %}
       State 2 different view
{% endif %}
{% django_stop_processing_template %}

{%if data.process_data %}
           Display some list of data
{% endif %}
{% django_stop_processing_template %}

 No data provided !

Upvotes: 4

Views: 1440

Answers (4)

Ni Xiaoni
Ni Xiaoni

Reputation: 1679

today I meet the same question. And I find this tag {% verbatim %} {% endverbatim %} .This works in Django1.5+ An example:

  {% verbatim %} 
  <div class="entry">
    <h1>{{ title }}</h1>
    <div class="body">
      {{ body }}
    </div>
  </div>
  {% endverbatim %}

You can also look below for more details:

Upvotes: 1

Burhan Khalid
Burhan Khalid

Reputation: 174682

I am not sure what your stop processing template logic would do; but a cleaner way to do your logic would be to write a custom tag that takes your arguments and then returns only the HTML relevant to your variables. This way you remove the if/else loops and instead replace all that with a simple {% do_stuff %} tag.

Edit

This is a very simple implementation to give you some idea on how the logic would go.

First, you create templates for each variation and store them somewhere django can find them.

Then, a simple tag that renders the exact template you want (this is non tested, psuedo):

from django import template
from django.db.models import get_model
register = template.Library()

class ProcessData(template.Node):
    def __init__(self, var_name):
        self.obj = get_model(*var_name.split('.'))
    def render(self, context):
        if self.obj.some_state:
           t = template.loader.get_template('some_markup_template.html')
           result = 'something'
        else:
           if self.obj.some_state_2:
              t = template.loader.get_template('some_different_html_view.html')
              result = 'something'
       else:
          if self.obj.process_data:
             t = template.loader.get_template('some_list_data.html')
             result = 'something'
          else:
             t = template.loader.get_template('no_data.html')
             result = 'something'
        return t.render(Context({'result': result}, autoescape=context.autoescape))

@register.tag
def process_data(parser, token):
    try:
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
    return ProcessData(arg)

Finally, in your template:

{% load my_tags %}
{% process_data data.mymodel %}

Upvotes: 4

Ritesh Kadmawala
Ritesh Kadmawala

Reputation: 743

Though I think @burhan's approach is better, you could also do what you want to do by using a custom tag that sets a context variable to a boolean and than outermost else part could also be converted into a if tag

#Set a context variable nodata to True 
{% setnodata True %}  
{%if data.some_state %}
    Display some markup
    #Set context variable nodata to False  
    {% setnodata False %}
{% endif %}

{%if data.some_state_2 %}
    State 2 different view
    #Set context variable nodata to False  
    {% setnodata False %} 
{% endif %}

{%if data.process_data %}
    Display some list of data
    #Set context variable nodata to False  
    {% setnodata False %}
{% endif %}

{% if nodata %}
    No data provided !
{ % endif %}

The setnodata custom tag simply sets the context variable nodata to True or False depending upon the argument.

Upvotes: 2

Zach Kelling
Zach Kelling

Reputation: 53859

You could use jinaj2 for templating that view (or the whole project), it supports if/elif/else branching:

{% if data.some_state %}
    Display some markup
{% elif data.some_state_2 %}
    State 2 different view
{% elif data.process_data %}
    Display some list of data
{% endif %}

There are a couple different packages which it easy use jinja2 in a django project, I've used both coffin and djinja for this.

Upvotes: 3

Related Questions