How to access template block from plugin within Django CMS Placeholder - django

I have the following code:
base.html
<html>
...
{% block test_block %}
{# Some stuff to render #}
{% endblock %}
...
</html>
main_template.html
{% extends "base.html" %}
...
{% block content %}
{% placeholder "content" %}
{% endblock %}
...
plugin.html
...
If I add my plugin to the page it renders in the placeholder block, as expected.
If I amend plugin.html to add the following:
plugin.html
...
{% block test_block %}
{{ block.super }}
{# Some more stuff to render #}
{% endblock %}
...
Then I receive an error:
'BlockNode' object has no attribute 'context'. Did you use {{ block.super }} in a base template?
If I try and extend either main_template.html or CMS_TEMPLATE (they seem to be the same?) from within plugin.html I get the following error:
maximum recursion depth exceeded while calling a Python object
How can I access and append to test_block from within my plugin?

In order to use a block you must, I believe, do so in a template which extends from a template where that block is defined.
However, to do what you want, CMS makes use of django-sekizai.
With this you can have this in base.html;
{% load sekizai_tags %}
<html>
...
{% render_block "test_block" %}
...
</html>
And then in plugin.html you can do;
{% load sekizai_tags %}
{% addtoblock "test_block" %}
Add this to my block
{% endaddtoblock %}
This is often used for CSS & JS blocks, but works perfectly well for what you want to do.

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.

Django Template overriding

I was wondering, when using templates in django, I'm able to extend other base templates and override some of the blocks in the base template. so my question is when I override, would the code in the overridden block still get rendered then overridden, or would it never be run and only the new block is rendered?
Example:
base.html
{% block menu %}
{% for option in menu %}
...Create the menu entries
{% endfor %}
{% endblock menu %}
extender.html
{% extends base.html %}
{% block menu %}
... some other tags
{% endblock menu %}
In this case does the original for loop in the base.html run if it gets overridden?
As far as I know the block will be overwritten unless you want to preserve its code in your extended template.
If you want to preserve the original block you can use {{ block.super }}
base.html
[...]
<body>
{% block header %}
base header content
{% endblock %}
[...]
</body>
extended.html
{% extends "base.html" %}
{% block header %}
{{ block.super }}
new content added
{% endblock %}
[...]
G.

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 %}

django template extend - all but one template

I have a piece of html that I want present in all pages, except one. If not for this page, I would have put it in the base.html and extended.
Is there a way other than putting the code individually in all the required pages?
From template-inheritance docs,
The template engine will notice the {% block %} tags in base.html and replace those blocks with the contents of the child template.
BUT
If the child template didn’t define the block, the value from the
parent template is used instead. Content within a {% block %} tag in a
parent template is always used as a fallback.
So in that case you can use {% block %} tag in the base.html.
{% block content %}
<!-- Your content here-->
{% endblock %}
You don't have to define that block in every template as the parent {% block %} is used as an fallback.
{% extends 'base.html' %}
So in your exceptional case just define that {% block %} tag with no data or something else.
{% extends 'base.html' %}
{% block content %}
<!-- Nothing goes here -->
{% endblock content %}
You can put it into a block that gets overridden with nothing in order to have it ignored. For example:
base.html
{% block content %}
<div>
This should show on all pages except for this one
</div>
{% endblock content %}
included-page.html (The div will be included on this page)
{% extends 'base.html' %}
ignored-page.html (The div will be ignored on this page)
{% extends 'base.html' %}
{% block content %}
{% endblock content %}

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.