Skip a level with {{ block.super }} - django

I have a 3rd party app that defines a bunch of templates (somewhat similar to how django-admin works). The base template defines a block with some content:
base.html:
<!doctype HTML>
<html><head>
<!-- blah blah -->
{% block very_kewl %}
<marquee><b><i><u>this is very kewl</marquee></b></i></u>
<!-- disclaimer: this is not valid HTML! -->
{% endblock very_kewl %}
</html>
Then a child template clears the block:
actual_page.html:
{% extends 'base.html' %}
{# very many other stuff, part 1 #}
{% block very_kewl %}{% endblock %}
{# very many other stuff, part 2 #}
What I want to achieve is to keep the "very kewl" content on the page.
An approach that works is to simply copy the entire actual_page.html into the project template dir and omit the line {% block very_kewl %}{% endblock %}. This works, but the downside is that I also have to repeat all the other parts of the template, some of which are likely to change in the future.
So the question is how can I show that "very kewl" content from the base template without also repeating all the other stuff in the actual_page.html?
Ideally, I would be able to do something like this, but of course, this doesn't work:
project_templates/actual_page.html:
{% extends 'actual_page.html' %}
{% block very_kewl %}{{ block.super.super }}{% endblock %}

Why not keep the HTML used in the base template's block as a separate template?
project_template/partials/very_kewl.html
<marquee><b><i><u>this is very kewl</marquee></b></i></u>
<!-- disclaimer: this is not valid HTML! -->
Now, just include it wherever the HTML needs to be used.
project_template/base.html
<!doctype HTML>
<html><head>
<!-- blah blah -->
{% block very_kewl %}
{% include 'partials/very_kewl.html' %}
{% endblock very_kewl %}
</html>
And in the grandchild project_templates/actual_page.html
{% extends 'actual_page.html' %}
{% block very_kewl %}{% include 'partials/very_kewl.html' %}{% endblock %}
So even at some point the block gets cleared up, the childs of that template can simply include the required HTML.

Related

Django; How to debug {% include '' %} tag within templates

Sometimes I get an empty string returned for my include tags which is impossible, because I have some static elements in it.
This is happening sometimes in my productive environment. How can I debug such an issue?
For example my footer or header disappears in some cases (Which I include within my "base.html") which I can't reproduce.
Thx
Example:
base.html
<html>
...
{% include "subdir/_header.html" %}
...
{% block content %}
<h1>Default Content</h1>
{% endblock %}
...
{% include "subdir/_footer.html" %}
</html>
home.html
{% extends "base.html" %}
{% block content %}
<h1>Home related Content</h1>
{% endblock %}
So if I load home.html my footer sometimes disappears. No idea why, no errors.
FOUND THE PROBLEM
A missing static file caused that kind of problem. Unfortunately I did not get an error.
I don't know the exact reason of this issue, but can you try with {% extends 'base.html' %}.
The difference between include and extends right here:
{% include %} vs {% extends %} in django templates
Your base html should be Extended and not Included... include is for small blocks of codes, like components... blog post, news, contact and that stuffs
base html
{% load static %}
<!DOCTYPE html>
<html lang="en-US">
{% include 'path/head.html' %}
{% block content %}{% endblock %}
{% include 'path/footer.html' %}
</html>
other pages
{% extends 'base.html' %}
{% load static %}
{% block content %}
<!-- Content from each page -->
{% endblock %}
Obs.: Include inside of includes dont work propely, you can get the data from first page in includes inside includes... for that i usualy use templatetags or context_processors, depending of your need.
Use django-debug-toolbar to debug your entire application in dev environment, you can see the entire request and the includes that you want
https://django-debug-toolbar.readthedocs.io/en/stable/

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 template language not working

#base.html
<html>
<head><title>Hello world</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
#child.html
{% extends base.html %}
{% block content}
This is the content that
comes here
{% endblock %}
but the html output of base.html not displaying content.? Why this template language not working ?
Template inheritance includes the parent template in the child, not the other way around.
Render child.html and you'll see your content surrounded by the base.html (parent) markup.
Also, you need to quote the parent template name:
{% extends "base.html" %}
{% block content %}
Content!
{% endblock %}

How do I wrap some html around a block in a django template?

I have a base template (base.html) like this:
<doctype html> etc etc
{% block content %}{% endblock %}
It is used by many other templates in my site, but I have a third party app that comes with its own templates which inherit from tp.html which in turn inherits from base.html. These templates are mostly fine but I need their content blocks to be wrapped in a div. I could change the third party templates to use a sub_content block and modify tp.html like so:
{% extends "base.html" %}
{% block content %}
<div class="third-party-app">
{% block sub_content %}{% endblock %}
</div>
{% endbock %}
but I don't want to have to modify all the templates in the third party app.
What I want is something similar to {$smarty.block.child} found in Smarty templates, or a way to achive the same. Any ideas?
You can use block.super like so:
3rd party template:
{% block content %}
<h1>3rd Party Content</h1>
{% endblock %}
your template:
{% block content %}
<div class="wrapper">{{ block.super }}</div>
{% endblock content %}
In base.html, add pre_content and post_content blocks either side of {% block content %}, then in tp.html add your and tags to these blocks. Slightly inelegant, but it'll work and you won't have to modify all your templates.

Django: nested content blocks with the same name

Is there a way to have content blocks with the same name?
base.html:
This is the template with the main layout.
<html>
...
{% block content %}
{% endblock %}
...
</html>
base_side_left.html:
This is the template with the main layout + sidebar on the left.
{% extends 'base.html' %}
{% block content %}
<div class='sidebar'>
</div>
{% block content %}
//This doesn't work because you can't have blocks with the same name//
{% endblock %}
{% endblock
I have a few reason why I am asking this:
It's easy to change the parent of a page without having to change the name of the content blocks.
I don't have to come up with names for my blocks. Like content-content, sidebar-content, etc
I got two solutions for this which I don't like because they ain't DRY:
Make the sidebar a partial and include it in the templates you need.
Add everything to the base template and overwrite those blocks you don't need.
If this isn't possible with Django Template can I do something like this with an other templating engine?
Small update:
So what I want to do is to be able to move the templates around in the template tree without to much hassle. It's not possible though without coming up with smart names for my content blocks but I thought I add this pretty diagram anyways.
No, you can't. From the Django docs on template inheritance:
you can't define multiple {% block %} tags with the same name in the same template. This limitation exists because a block tag works in "both" directions. That is, a block tag doesn't just provide a hole to fill -- it also defines the content that fills the hole in the parent. If there were two similarly-named {% block %} tags in a template, that template's parent wouldn't know which one of the blocks' content to use.
I'm not clear on why you want to do this.
It's easy to change the parent of a page without having to change the name of the content blocks.
There's only one {% block %} tag with a given name, and there's only one {% extends %} tag as well. I don't see any difference in difficulty.
I don't have to come up with names for my blocks. Like content-content, sidebar-content, etc
Anyone maintaining your code will quickly lose track of which content block is effective and get confused. Besides, the names should have something to do with what the {% block %} is supposed to do. So I'm wondering why you'd have two templates, one including another, with blocks that are exactly the same.
Another point from the docs:
If you find yourself duplicating content in a number of templates, it probably means you should move that content to a {% block %} in a parent template.
This lets you make the duplicated markup the default, and you can override it in those places where needed.
This may be helpful, too:
If you need to get the content of the block from the parent template, the {{ block.super }} variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }} will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.
From what I can tell, this is probably your best choice:
Make the sidebar a partial and include it in the templates you need.
How is this not DRY? You have to repeat the {% include %} tag?
I think there's a better design solution that would work for you, but you haven't given enough info on what you're trying to accomplish for me to help further.
EDIT: Looking at your example, you can do all that with a single template. CSS will take care of you here.
page_template.html:
<!DOCTYPE html PUBLIC -- ... -->
<html>
<head>
<!-- ... other header fields ... -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<base href="{{ host }}{{ root }}{{ path }}" />
<title>{% block title %}Untitled{% endblock %}</title>
<link rel="icon" type="image/png"
href="{{ root }}static/images/favicon.png" />
<link rel="stylesheet" type="text/css"
href="{{ root }}static/css/general.css" />
<!-- other header fields here -->
{% block head %}{% endblock %}
</head>
<body class="{% block page_class %}no_sidebar{% endblock %}">
<div id="page_header">
<!-- page heading here -->
</div>
<div id="sidebar">
{% block sidebar %}<!-- default sidebar here -->{% endblock %}
</div>
<div id="banner">
{% block banner %}{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
general.css:
body.no_sidebar div#sidebar,
div#banner
{
display: none;
}
div#sidebar
{
width: 20%;
}
body.with_sidebar div#sidebar
{
float: left;
}
body.with_banner div#banner
{
display: block;
}
body.right_sidebar div#sidebar
{
float: right;
}
Then your pages just look like, in the order of your examples:
plain_old_page.html:
{% extends base.html %}
{% block content %}
<!-- content goes here -->
{% endblock %}
page_with_left_sidebar.html:
{% extends base.html %}
{% block page_class %}with_sidebar{% endblock %}
{% block sidebar %}
<!-- sidebar goes here, if different from default -->
<!-- otherwise omit this section -->
{% endblock %}
{% block content %}
<!-- content goes here -->
{% endblock %}
page_with_left_sidebar_and_banner.html:
{% extends base.html %}
{% block page_class %}with_sidebar with_banner{% endblock %}
{% block sidebar %}
<!-- sidebar goes here, if different from default -->
<!-- otherwise omit this section -->
{% endblock %}
{% block banner %}
<!-- banner goes here -->
{% endblock %}
{% block content %}
<!-- content goes here -->
{% endblock %}
page_with_right_sidebar.html:
{% extends base.html %}
{% block page_class %}right_sidebar{% endblock %}
{% block sidebar %}
<!-- sidebar goes here, if different from default -->
<!-- otherwise omit this section -->
{% endblock %}
{% block content %}
<!-- content goes here -->
{% endblock %}