Django: use the forloop value from a parent template - django

Can I get the forloop value out of a parent template forloop? I.e.:
parent.html
{% extends 'base.html' %}
{% block content %}
{% for i in nnn %}
{% include child.html %}
{% endfor %}
{% end block %}
child.html
{% extends 'base.html' %}
{% block content %}
{{ forloop.counter from parent.html }}
{% endblock %}
def ViewParent(request):
return render_to_response('parent.html', {}, context_instance)

The include template tag supports the passage of arguments using the with keyword.
parent.html:
{% extends 'base.html' %}
{% block content %}
{% for i in nnn %}
{% include child.html with loop_counter=forloop.counter %}
{% endfor %}
{% end block %}
child.html:
{{ loop_counter }}
Note that you probably don't actually mean to extend the child template from the same base template as the parent, so I have omitted that in this example.

Related

Nesting Django block with {% include %}

I am trying to nest blocks with Django 3. I have sections of html that are sometimes reused on a page. I don't think I would have to resort to duplicating templates, but I can't get it to work;
I have this template
{% extends 'base.html' %}
{% include 'site_part.html' %}
{% block content %}
Some Content
<br>
And here I insert the child content
{% block part_of_site %}
{% endblock %}
{% endblock %}
And the site_part_html is like this;
{% block part_of_site %}
Okay, i am loaded!
{% endblock %}
In the base.html I have only this:
{% block content %}
{% endblock %}
I'd expect it to render the "Okay, i am loaded!" string in the resulting page, in the content block. However, it remains empty. I've looked, but most examples are far more advanced then what I need and I can't get those to work either.
If I remove the extends statement at that start and the block content lines, it does load the included html.
Basically, I have a site part that sometimes is need, and I'd like to included that based on some templating. Otherwise, I'd have duplicate that code for each of the pages that it occurs on.
You may call the content from the block 'part_of_site' in any child template using {{ block.super }} like this:
{% extends 'site_part.html' %}
{% block content %}
Some Content
<br>
{% block part_of_site %}
{{ block.super }}
{% endblock %}
{% endblock %}
You should use {% extends 'base.html' %} in the 'site_part.html' template. All children of 'site_part.html' will also be a descendant of base.html
{% extends 'base.html' %}
{% block part_of_site %}
Okay, i am loaded!
{% endblock %}
If you want to use {% include %} instead, change your code like this:
{% extends 'base.html' %}
{% block content %}
Some Content
<br>
{% include 'site_part.html' %}
{% endblock %}
You need to move your {% include 'site_part.html' %} into the {% block content %} block.
content.html
{% extends 'base.html' %}
{% block content %}
Some Content
<br>
And here I insert the child content
{% include 'site_part.html' %}
{% block part_of_site %}
{% endblock %}
{% endblock %}
Then, in your view you need to return your content template. I named it content.html here.
def your_view(request):
return render(request, "content.html")
You can put the include anywhere inside the content block, it doesn't have to be right before the part_of_site block.

{% block something %} always being displayed despite being False in an if-statement

I have two types of blog articles. Regular blog articles, and translation articles. They both have different html markup. I have a boolean variable translation_bool in my models to check if it is a translation article or not. If it is I want it to display my {% block translation %} and if not {% block translation %}. It worked with plain html code and not using html tags. But I had so much reusable code that it got troublesome to manage.
So my question is: why is this happening despite it being inside of an if statement.
Article template:
{% extends "base_generic.html" %}
{% load static %}
{% block js %}...{% endblock %}
{% if blogpost.translation_bool == True %}
{% block translation %}....{% endblock %}
{% else %}
{% block content %}...{% endblock %}
{% endif %}
{% block sidebar %}....{% endblock %}
In Base Generic Template:
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-8">
{% block content %}{% endblock %}
{% block translation %}{% endblock %}
</div>
<div class="col-md-3">
{% block social_media %}...{% endblock %}
{% block sidebar %}...{% endblock %}
</div>
</div>
</body>
This is because blocks not defined in child template will render value from parent template. So in your case you should perform validation inside parent template. Or if it's impossible override blocks in child with empty content:
{% block translation %}
{% if blogpost.translation_bool == True %}
{{ block.super }}
{% else %}
{% endif %}
{% endblock %}
{% block content %}
{% if blogpost.translation_bool == False %}
{{ block.super }}
{% else %}
{% endif %}
{% endblock %}
Note {{ block.super }} will render content from parent template.

Django overwrite parts in inherited templates

I have set up the following templates
base.html
{% extends 'base/main_base.html' %}
{% block main-content %}
<h1>Header stuff<h1>
...
{% block article-content %}
{% endblock %}
{% endblock %}
article.html
{% extends 'base.html' %}
{% block article-content %}
<h2>Content</h2>
<p>More content</p>
{% endblock %}
Now, I connected a view to the article.html, and I want use the dynamic view data to overwrite the 'header stuff' in the 'base.html' template. Problem is, the view is connected to the article.html, which inherits from the base.
Is there a way to override parts of the base template from the child template?
You could create another template block in your base.html
{% extends 'base/main_base.html' %}
{% block main-content %}
<h1>{% block header %}Header stuff{% endblock %}<h1>
...
{% block article-content %}
{% endblock %}
{% endblock %}
and overwrite the block in your article.html
{% extends 'base.html' %}
{% block header %}My overwritten headline{% endblock %}
{% block article-content %}
<h2>Content</h2>
<p>More content</p>
...
{% endblock %}
You could also check, in base.html, if a "header" value is injected to the template from the article (or any other view):
base.html
{% extends 'base/main_base.html' %}
{% block main-content %}
<h1>
{% if header %}
{{ header }}
{% else %}
Header stuff
{% endif %}
<h1>
...
{% block article-content %}
{% endblock %}
{% endblock %}

Expanding a template in an other templates' block

I have to do a little websites rendering a few pages with static content.
The pages are based on a base.html template, this template has a content block.
The pages may have (or not) an aside element (always the same aside).
Thus far I can do something like this :
page.html :
{% extends "base.html" %}
{% block content %}
{% include "page-content.html" %}
{% endblock %}
page-content.html :
{% extends "content-with[out]-aside.html" %}
{% block content %}
foo
{% endblock %}
content-with-aside.html :
<div>
<div>
{% block content %}
{% endblock %}
</div>
<aside>
aside
<aside>
</div>
content-without-aside.html :
<div>
<div>
{% block content %}
{% endblock %}
</div>
</div>
But that supposes using a template with no usefulness but defining if the page has or not the aside.
I could also define a base-with-aside.html and a base-without-aside.html templates. But could I do something like this?
page.html :
{% extends "base.html" %}
{% block content %}
{% expandblock "content-with[out]-aside.html" %}
{% block content %}
foo
{% endblock %}
{% endexpandblock %}
{% endblock %}
In Jinja perhaps?
At worst case I could define a custom template tag, but I would like to know it there already is a feature like this.

Is there a way to pass a variable to an 'extended' template in Django?

I want to add some flexibility to my layout template, but I can't find any way to do so.
I'm looking for a way to extend my layout template with variable, i.e. to pass a variable up in the template tree, not down.
# views.py
def my_view_func(request):
return render(request, "child.html")
# child.html
{% extends 'layout.html' with show_sidebar=True sidebar_width_class="width_4" %}
<div>Templates stuff here</div>
# layout.html
{% if show_sidebar %}
<div class="{{ sidebar_width_class }}">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
I have to maintain four templates with a difference in a few lines of code. For example, I have two templates that differ from each other by a sidebar width class. Am I doing something wrong?
I suspect that block is what you are looking for in the first place.
Form your block inside the base template like this:
{% block sidebar_wrapper %}
{% if sidebar %}
<div class="width{{sidebar_width}}">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
{% endblock sidebar_wrapper%}
And on your child template:
{% extends 'layout.html' %}
{% block sidebar_wrapper %}
{% with sidebar=True sidebar_width=4 %}
{{ block.super }}
{% endwith%}
{% endblock sidebar_wrapper%}
What you need is an include template tag. You can include a template in another template and render that with specific context.
{% include 'layout.html' with sidebar=True sidebar_width=4 %}
Check docs here: https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#include
You can achieve this with some technique. I'll show the code then explain below.
# layout.html
{% block content %}
{% if show_sidebar %}
<div class="{{ sidebar_width_class }}">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
{% endblock %}
# child.html
{% extends 'layout.html' %}
{% block content %}
{% with show_sidebar=True sidebar_width_class="width_4" %}
{{ block.super }}
{% endwith %}
{% endblock %}
In layout.html, wrap everything inside {% block content %}
In child.html, {{ block.super }} is like python's super(), which renders everything in the parent template's block. So if you wrap it inside {% with %} tag, all variables that you declare there will be available inside the parent template as well.