Conditional include tag in Django - django

I've ran into very strange behavior of Django template system. I have a template file, namely test.html, which recursively includes itself:
{% include "test.html" %}
Of course, such template has no chance to be rendered, since there is no finishing condition. OK, let's try the following:
{% if test_false %}{% include "test.html" %}{% endif %},
where test_false is a variable passed to template and equal to False.
One expects that it just will not include anything, but it does:
RuntimeError at /test/
maximum recursion depth exceeded while calling a Python object
I don't get it. Include tag can take arguments from current context, so I doubt it is executed before any other part of the page. Then why does it ignore condition tag?

Django has optimization that include templates that are given by constants at compilation.
Set name of template to variable and include it in that way:
{% include test_template %}
Django will not be able to use it's optimization and your code should work.

Like Thomasz says, Django can only make this optimization if the path is defined as a constant string in the including template - like so:
{% include "test.html" %}
But I would rather not have to put the template path in the context from Python code.
So here is a slightly more self contained way of achieving the same result - wrap the include in a with:
{% with "test.html" as path %}
{% include path %}
{% endwith %}

Related

Django. How to kind of "spread" object when passing as with parameter to include?

I have a component which i include like that:
{% include "components/item_link.html" with target="_blank" href=link.href icon=link.icon text=link.text %}
There are lots of repetitions of link.. Is there a way to "spread" object and include it like that?
{% include "components/item_link.html" with target="_blank" ...link %}
Assign the link variable directly like:
{% include .... link=link %}
Then in the included template use their single values as:
link.href
link.icon
link.text
If you can't modify the included template code, you can create an intermediate template which assigns the above variables and call the original include with their respective href=link.href icon=link.icon text=link.text so you avoid to repeat everything every time you use it.
Update
Add a link parameter, you can still use the parameters but then in the included template you can also detect if link is set when the parameter isn't set.
For example:
{% include "components/item_link.html" with target="_blank" link=link %}
in components/item_link.html:
<a href="{%if href%}{{href}}{%elif link%}{{link.href}}{%endif%}> ...

Tag or inherit the same code in Django template with minor changes

I have a bunch of code that I will need to use repeatedly on a page, and on multiple pages. For example, here is a shorter version of the code:
<a href="#"
data-toggle="popover"
title="{% for terms in s_terms %}{% if terms.slug == 'neuron' %}{{terms.title}}{% endif %}{% endfor %}"
data-content="{% for terms in s_terms %}{% if terms.slug == 'neuron' %}{{terms.para_one}}{% endif %}{% endfor %}">
Toggle popover
</a>
There is a lot more code in the block. Now, for obvious reasons I do not want to keep repeating such large chunks of code. I am a fan of the DRY approach.
However, I can't figure out how to render this same piece of code repeatedly. The only thing that would change is the word = "neuron" in there. I thought of using template tags, but that didn't work.
I tried saving the code as a separate file, and inherit it within my template, but then I can't change the keyword ('neuron'). I also tried creating a separate dynamic page, and include that in my Django template, but looks like the include tag only works for templates, and not for dynamic pages.
Can anyone help, please? Thank you, in advance.
You could use Django template built-in template tag include.
From the documentation:
Loads a template and renders it with the current context. This is a
way of “including” other templates within a template.
So, you can just extract your snippet in a separate template and then use it with:
{% include "snippet_template.html" %}
Additionally, you can pass a variable to the include template using the with keyword - you would use this to pass your word parameter:
{% include "snippet_template.html" with word="neuron" %}
As #bonidjukic wrote the include statement is what you search.
But include statement inside for-loop could reach one weakness of Django template Engine (vs Jinja). You include just variables, so it will be fast.
In the case of needing tags (like trans), Django will load tags at each include. Where Jinja will have global "tags".
So just be careful, with how you DRY you templates.

what is difference between {{}} and {% %} in django templates

I am very new to django and working on it.. I visited a html file and dont know the difference between {{}} and {% %} in html files used
as here
{% load static %}
Thanks a lot
You can use
{% %} For sentences such as if and for or to call tags such as load, static, etc.
{{ }} To render variables in the template.
Read More about it at Django Docs
{% %} is for displaying code and {{}} is for displaying variables
There are three things in the template in Django
First is template variable and the second thing is template tag and third and last is template filter
so we write a template variable is {{}}
and write a template tag is {% %}
third and last is template filter {{variable |filter:arg}}
I'm new too for Django, so if i'm wrong, please someone correct me.
The difference between they are:
{{variable}} is used to use a variables. When the template encounters a variable, it evaluates that variable and replaces it with the result.
You also can use filters {{variable|filter}} like this:
{{name|length}} in this case you will use a variable "name" and return the length of that variable.
{%tag%} could use for loops or logic, or load external information into the template to be used by later variables. You can create block tags to help extend other html files parts. Also you can create custom tags.
A good place to see how to do it:
https://www.codementor.io/hiteshgarg14/creating-custom-template-tags-in-django-application-58wvmqm5f
Tags like loops and block, need to be closed.
{% %} for IF ELSE CONDITIONS and FOR LOOP etc
{{ }} for veriables that rendered from view function also used in FOR LOOP veriables like
`enter code here`
{% for obj in qs%}
{{ obj.veriable_name }}
{% endfor %}

Django's {% include with var="val" %} updates context

I just figured out, that if you include subtemplate using with, variables will be available in base template. Very easy to reproduce:
Test: {{ test }}
{% include "tpl.txt" with test="passed" %}
Test: {{ test }}
Output:
Test:
Test: passed
Is it a bug?
UPD. I must say that inside tpl.txt there is inclusion tag with take_context=True. Also this inclusion tag do this:
#register.inclusion_tag('my_tag.txt', takes_context=True)
def my_tag(context):
context.update({'new': 'key'})
return context
If you don't update context, or if you do context['new'] = 'key' it works as expected. If you do update - all the variables you pass to {% include %} using with become available later in template. Still it's kind of wierd, because variables become available in parent template, and not updated keys ("new") become available, but {% include %} variables. The problem is localized though.

Django: cannot pass variable to included template?

I got a problem where I want to use template including in Django.
Here is the real example:
I got 3 files:
home.html (will get the context variable passed from Views)
base.html (the skeleton template file)
and the header.html (included by base.html).
If I put the code below directly in base.html without including header.html, the {{title}} variable passed from home is correctly called. But if I include the header.html in base.html, the {{title}} variable's value cannot be called.
<title>{% block title %}{% endblock %} | {{ SITE_INFO_TITLE }}</title>
Is there any solution to this problem? Thanks.
Could you just pass in a variable within the {% include %} tag? It's documented here: https://docs.djangoproject.com/en/1.5/ref/templates/builtins/#include
{% include "name_snippet.html" with person="Jane" greeting="Hello" %}
As far as I know blocks and variable are distinct in django.
If you want to pass title as a context variable you have to set it using a declaration in base.html such as :
{% include "header.html"%}
Which in turn contains :
{% block title %} {{title}} {%endblock%}
You can also set it in home like this.
{% block title %} Home page {%endblock%}
But I also try to set in the template context.
Without the title block.
def test_view(ctx):
xa = { "title":"Sommaire"}
return render_to_response("test.html",xa)
I think you can also see the with template tag I think it is possible to set a context variable using this tag.
You can use Inclusion Tags to render an additional template from within a Django template. You can additionally pass the 'child' template context from the 'parent' template.
It's a little involved for your use case but it solves your problem. I tend to use it when I'm looping a list to render each item with a custom template. I can then reuse that template elsewhere without duplicating the markup if I need to render another item of the same type.