Compositional Templates Django - django

What is the best way to create modular templates?
For example, if I have something like this:
#base file:
{header}
{block content}
{footer}
#main file:
{extends base}
{block content definition}
#product file:
{extends base}
{block content definition}
This is the django way from what I understand - filling in the blanks.
Now, my question is what if I needed a page like this:
{header}
{main}
{product}
{footer}
Basically, the main, and product are both inside the base file. I could try a deep inherit (a page that has main, which then consecutively loads product) but that does not work since the files both define 'content', and that is not possible in Django

You need do two templates "_main.html" and "_product.html" which don't extend base, just their own content.
After that you can use them via include tag https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
#main.html file:
{% extends 'base.html' %}
{% block content %}
{% include '_main.html' %}
{% endblock %}
#product.html file:
{% extends 'base.html' %}
{% block content %}
{% include '_product.html' %}
{% endblock %}
#and what you want:
{% extends 'base.html' %}
{% block content %}
{% include '_main.html' %}
{% include '_product.html' %}
{% endblock %}
{% block footer %}
{% endblock %}

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.

Reuse same "block" of html in multiple django templates

Currently, I have two html template that extends from a base.html:
page1.html:
{% extends 'dashboard/base.html' %}
{% block tittle %} Dashboard1 {% endblock %}
... code ...
Code_block_1
{% endblock %}
page2.html:
{% extends 'dashboard/base.html' %}
{% block tittle %} Dashboard2 {% endblock %}
... code ...
Code_block_1
{% endblock %}
Both html share the same Code_block_1.
I was thinking about about creating another html called Code_block_1.html to consolidate this repeating piece of code. Then, insert Code_block_1.html into page1.html and pag2.html. Django only lets you extend once. How do I get around this problem?
Thanks.
Simply create another HTML file called code_block_1.html and then inside both page1.html and page2.html use include like this:
<!-- page1.html -->
{% extends 'dashboard/base.html' %}
{% block tittle %} Dashboard1 {% endblock %}
... code ...
{% include 'code_block_1.html' %}
{% endblock %}
<!-- page2.html -->
{% extends 'dashboard/base.html' %}
{% block tittle %} Dashboard2 {% endblock %}
... code ...
{% include 'code_block_1.html' %}
{% endblock %}

Djangocms template not showing up

I have a basic DjangoCMS up and running.
base.html contains:
{% block content %}{% endblock content %}
I also have feature.html:
{% extends "base.html" %}
{% load cms_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
{% block content %}
<div>
{% placeholder "feature2" %}
</div>
<div class="jumbotron"">
{% placeholder "feature" %}
</div>
<div>
{% placeholder "content" %}
</div>
{% endblock content %}
I added the "feature2" placeholder in the above, and it correctly displays for editing on the site.
I then added a new line to base.html:
{% block base_logo %}{% endblock base_logo %}
and created a new file, base_logo.html:
{% extends "base.html" %}
{% load cms_tags %}
{% block base_logo %}
<div>
{% placeholder logo %}
</div>
{% endblock base_logo %}
I expected this to also appear on the site for editing, but it doesnt. I have added the base_logo.html to the CMS_TEMPLATES in settings.py and TEMPLATE_DIR is also pointing correctly.
What else do I need to do for Djangocms to pick up my new template?
Take a look at template inheritance.
You're trying to use two {% extends %} tags, which won't work. You should use the {% include %} tag for base_logo, because it seems you'd want to include this in many templates. This question provides more info.

How to extend a base.html using two different files?

I'm writing an application in which user can choose one of several tools for data analysis and open it in a panel on main page. Is it possible to use django "extends" and have each tool defined in different file?
The minimal example of what im strugling with would be like this:
base.html
<div>
{% block left_panel %}
left block
{% endblock content%}
</div>
<div>
{% block right_panel %}
right block
{% endblock %}
</div>
and sample left_panel and right_panel tools:
left1.html
{% extends "base.html" %}
{% block left_panel %}
<p>TEST left 1</p>
{% endblock %}
right1.html
{% extends "base.html" %}
{% block right_panel %}
<p>TEST right 1</p>
{% endblock %}
Is there a way to render the base.html with both blocks overwriten?
I believe that the best way to implement your requirement is to create a new template that extends base.html and includes left1.html and right1.html. Something like this:
{% extends "base.html" %}
{% block left_panel %}
{% include "left1.html" %}
{% endblock content%}
{% block right_panel %}
{% include "right1.html" %}
{% endblock %}
Update based on OP's comment: Actually you just need one configurable template, not 100. Let's say that based on the tools the user selects, your view passes the left_tool and right_tool context variables to your template. Now, you can easily do something like this:
{% block left_panel %}
{% if left_tool == "tool1" %}
{% include "left1.html" %}
{% elif left_tool == "tool2" %}}
{% include "left2.html" %}
etc ...
{% else %}
{% include "left10.html" %}
{% endif %}
{% endblock content%}
You'll do the same with the right panel. Of course the above is a little naive and definitely not DRY -- instead you could for instance generate the name of the template to be included in the view and pass it directly to the template, or use a custom node etc.

Django: with tag outside blocks

It seems like the 'with' tag is not working if it is declared outside of a block as this:
{% extends 'base.html' %}
{% with my_var=1 %}
{% block test1 %}
{{my_var}}
{% endblock %}
{% block test2 %}
{{my_var}}
{% endblock %}
{% endwith %}
The template above simply displays nothing since my_var is NOT passed inside those blocks.
How can I overcome this?
I came to Django from using Tornado with Jinja2 and I was being driven insane by the inability to set variables that (a) could be defined in the template (not view) and (b) would be available in the base template that this derives from. Looking at a little four-line piece of code from django-libs, I was able to rig up something like this that worked well. Here is an example of a title string that should appear in various blocks.
settings.py -- add to TEMPLATES (Django 1.10+)
TEMPLATES = {
...
builtins = ['mysite...wherever...templatetags',]
}
mysite.whereever.templatetags.py
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def setvar(context, key, value):
context.dicts[0][key] = value
return ''
base.html
{% block settings %}
{% comment %}
Put this at the TOP of the template before
any blocks that use variables.
{% endcomment %}
{% endblock settings %}
<html>
<head><title>{{title}}</title></head>
<body><h1>My Site: {{title}}</h1>
{% block body %}
{% endblock body %}
</body></html>
menu.html -- a template that does not set 'title' in views:
{% extends "base.html" %}
{% block settings %}
{{ block.super }} {% comment %}optional{% endcomment %}
{% setvar 'title' 'Menu' %}
{% endblock %}
{% block body %}
<ul><li>Fish</li><li>Steak</li></ul>
{% endblock %}
Now the title will appear in two places in the HTML even though it is defined in the derived template but appears in the top template.