3

I have a string that looks like

string '''
    <html>
        <head>
            {% block head %}{% endblock %}
            ... other stuff ...
        </head>
        <body>
            {% block body %}{% endblock %}
           ... other stuff ...
        </body>
    </html>
'''

I would like the following django template to inherit from the above string:

{% block head %}
    ... other stuff ...
{% endblock %}

{% block body %}
    <h1>Other stuff</h1>
{% endblock %}

Since the string is not in a file a can't just specify it's filename to the template rendering engine. Any ideas?

JBernardo
  • 32,262
  • 10
  • 90
  • 115
Trevor
  • 13,085
  • 13
  • 76
  • 99

2 Answers2

6

In order to implement string-only template extender, you would probably have to implement your template loader. Actually, a much cleaner solution is to use threed's suggestion below. Pass a parent Template() in the context rather than the name of disk template:

>>> from django.template import Context, Template
>>> extend_me = Template("Before A. {% block a %}{% endblock %}. After A")
>>> str_template = "{% extends parent %} {% block a %}This is inside A{% endblock %}"
>>> Template(str_template).render(Context({"parent": extend_me}))
u'Before A. This is inside A. After A'

Unfortunately this doesn't seem to work on django 1.3, possibly due to bug #7377 (you can't use the extends and block tags in string templates). Though it does work fine in 1.2. So if you happen to be running 1.3, you can look up the history of this question and use my hack :)


The extends template tag allows you to specify a variable name (since ver 1.0).

There's an example of it's usage in this question: How do I use Django's template extends variable?

Community
  • 1
  • 1
Seth
  • 45,033
  • 10
  • 85
  • 120
  • That still only allows you to extend a physical file. What if you want to extend some html template contained in a python string variable (e.g. strHTML = '{% block content %}{% endblock %}')? – Trevor Jul 29 '11 at 07:55
  • Sorry, I read your question wrong. See update. It's a first-class hack, but it works. – Seth Jul 29 '11 at 19:31
4

It turns out there's an even simpler way to achieve this:

from google.appengine.ext.webapp import template

parent = template.Template("<html><body>{% block content %}{% endblock %}</body></html>")
path = os.path.join(os.path.dirname(__file__), 'index.html')
template.render(path, template.Context({"baseTemplate": parent}))

Where the index.html file looks like this:

{% extends baseTemplate %}
{% block content %}
    <h1>Hello World!</h1>
{% endblock %}

In this case, the template object (as opposed to just a string) is passed into the context of the child template and used as the variable in the 'extends' tag.

Trevor
  • 13,085
  • 13
  • 76
  • 99