Search code examples
djangotemplatesrenderrender-to-string

Django 1.6 - parse template tags after import/parse from view


Firstly, I'm relatively new to Django, so forgive me if there's some fundamental misunderstanding on my part. I'm looking to parse some Django template tags that are imported as a part of a Django render. The end issue I'm seeing is the HTML/JS portions are being correctly called and displayed, but the last Django tags are being rendered as plain text on the page. I realize it's because I'm rendering the view before one step too early, but I'm not sure how to go about this correctly.

Here's the basic call stack (simplified):

template1

{% extends base.html %}
{% block main_content %}
   {{ block.super }}
   <div id="col1" class="chart-col" style="float: left; width: 33%;">
       {% block col1 %}
       {% endblock col1%}
{% endblock main_content %}

template2:

{% extends template1.html %}
{% block main_content %}
{% for DATA in DATALIST %}
    {{ DATA|safe }}
{% endfor %}
{% endblock main_content %}

python code that generates desired Django / HTML for the above DATALIST in template2:

def chartdisplay(block_var, othervars):
  text = "{% block block_var %} \n {{ block.super }} \n"
  text += "<html to generate data display goes here>"
  text += "{% endblock block_var %}
  return text

the above python is passed to the Django View.py:

def dataview(request):
  datapull = model.object.filter(**kwargs) #generic data pull
  #date-time handler
  dthandler = lambda obj: (
                         obj.isoformat()
                         if isinstance(obj, datetime.datetime)
                         or isinstance(obj, datetime.date)
                         else obj)
  data = {'data': datapull}
  chart_html = [
                     chartdisplay(block_var="col1", other_unique_vars),
                     chartdisplay(block_var="col2", other_unique_vars),
                     chartdisplay(block_var="col2", other_unique_vars),
                     chartdisplay(block_var="col3", other_unique_vars)
                   ]
   context = {'data', jsondump(data, default=dthanlder), 'charts': charts_html)

   return render(request, 'path/to/template2.html', context)

Now, the main issue is the resulting HTML that is displayed displays the HTML and JS fine, but has the Django template tags exposed as text and does not direct the chartdisplay into the desired divs. E.g. template2.html is viewed as:

{% block col1 %} {{ block.super }}
<html/D3 chart is displayed fine>
{% endblock col1 %}

{% block col2 %} {{ block.super }}
<html/D3 chart is displayed fine>
{% endblock col2 %}

{% block col2 %} {{ block.super }}
<html/D3 chart is displayed fine>
{% endblock col2 %}

{% block col3 %} {{ block.super }}
<html/D3 chart is displayed fine>
{% endblock col3 %}

I've tried a few various band-aid fixes but I'd rather just understand how to do this properly. The one thing I've tried but am probably misunderstanding is, before the return render step:

def dataview(request):
  ...
  rendered = render_to_string('path/to/template12.html', context, context_instance=RequestContext(request))
  return render(request, 'path/to/template2.html'/, rendered)

Thanks for you help. Please let me know if any clarification is needed!


Solution

  • You don't have to use render, it's just a shortcut that takes a request, template name and context, and returns an http response with the rendered context.

    That's not what you want in this case. You have a template string rendered that you wish to render. The low level API to render a template is explained here in the docs.

    from django.template import Context, Template
    from django.http import HttpResponse
    
    def dataview(request):
      ...
      rendered = render_to_string('path/to/template2.html', context)
      template = Template(rendered)
      return HttpResponse(template.render(Context(context)))
    

    You may have to use the verbatim tag so that your blocks and extends tags are not evaluated when you call render_to_string on the first template. For example

    {% verbatim %}
    {% extends template1.html %}
    {% block main_content %}
    {% endverbatim %}
    {% for DATA in DATALIST %}
    {{ DATA|safe }}
    {% endfor %}
    {% verbatim %}
    {% endblock main_content %}
    {% endverbatim %}