The Python Oracle

Python / Django - If statement in template around extends

This video explains
Python / Django - If statement in template around extends

--

Become part of the top 3% of the developers by applying to Toptal
https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Ominous Technology Looping

--

Chapters
00:00 Question
00:30 Accepted answer (Score 25)
00:58 Answer 2 (Score 26)
02:05 Answer 3 (Score 5)
03:27 Answer 4 (Score 0)
04:06 Thank you

--

Full question
https://stackoverflow.com/questions/5043...

Accepted answer links:
[refer to the documentation]: http://docs.djangoproject.com/en/dev/ref...

Answer 2 links:
[user Rafael]: https://stackoverflow.com/users/1798089/...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #django #djangotemplates

#avk47



ANSWER 1

Score 26


While you may not wrap extends in logic blocks, since it must be the first tag if used, it can still accept variables, including filters. This should fit your purpose nicely:

{% extends ajax|yesno:"base_ajax.html,base.html" %}
{# stuff #}

Note: the yesno filter also accepts null values (None) as the third choice, and if you do not specify one (as in this case), it will fallback to converting it to False (i.e. it will return the second choice). This allows you to not specify the ajax variable in your template without breaking it.


Suggested by user Rafael:

{% extends request.is_ajax|yesno:"base_ajax.html,base.html" %}
{# stuff #}

This will only work if you are using a RequestContext context instead of a plain Context object and you have the request context processor enabled, or alternatively, if you insert the request object in your template context.




ACCEPTED ANSWER

Score 25


You cannot do it like that. You can however set a variable and use that to choose the template to extend:

{% extends my_template %}

Then in python code you write something like:

if ajax:
    template_values['my_template'] = 'base_ajax.html'
else:
    template_values['my_template'] = 'base.html'

You may wish to refer to the documentation for more information.




ANSWER 3

Score 6


I was looking for the solution of the same problem and came with a bit better workaround than suggested by Klaus Byskov Hoffmann. It is better because you don't have to have 2 separate base templates for ajax and non-ajax requests and, which is more important, you don't have to define if statement that will define which base template to use in EACH controller.

In your case the solution would be:

page.html

{% extends "/base.html" %}
{% block body %}
    hello world
{% endblock body %}

base.html

{% if not ajax %}
<html>
    <head></head>
    <body>
        LOGO and other stuff...

{% endif %}{% block body %}{% endblock body %}{% if not ajax %}

        FOOTER
    </body>
</html>
{% endif %}

So, base.html is always included but it prints its content only when not ajax.

UPDATE: This can be simplified by creating and adding a new ConextProcessor that will populate ajax context variable from the HttpRequest.is_ajax(), so you don't have to do anything extra in your controllers and templates at all.




ANSWER 4

Score 0


If you don't want to "extend" a parent template, you can always create an empty file called null.html and extend that. Kind of hacky, but easy to understand.