Twig: variable override set in previous template - templates

I have 2 templates and I want to override the variable body_class from main template. This is the code I have so far.
Main Template:
{# main.html.twig #}
<!DOCTYPE html>
<html>
<head>
{% block head %}
{% block head_meta %}
// ...
{% endblock %}
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}
// ...
{% endblock %}
{% block icon %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
{% endblock %}
{% endblock %}
</head>
{% set body_class = '' %}
<body class="main {{ body_class }}">
{% block navi %}{% endblock %}
{% block error %}{% endblock %}
{% block body %}{% endblock %}
{% block footer %}{% endblock %}
{% block javascripts %}
// ...
{% endblock %}
</body>
</html>
Second template:
{# dashboard.html.twig #}
{% set body_class = 'dashboard' %}
{% extends 'main.html.twig' %}
{% block head %}
{{ parent() }}
{% endblock %}
{% block head_meta %}
{{ parent() }}
{% endblock %}
{% block title %}Dashboard!{% endblock %}
{% block body %}
I'm dashboard!
{% endblock %}
I tried placing {% set body_class = 'dashboard' %} before extend statement and after, but that didn't work. What am I doing wrong?
Thank you.

You should not set body_class in your main.html.twig file. dashboard.html.twig is all good, just change main.html.twig:
Remove {% set body_class = '' %} line and change <body class="main {{ body_class }}"> to <body class="main {{ body_class|default('') }}">.
That way you have your body_class variable value '' as a default value when it's not defined and 'dashboard' when you set it from your dashboard.html.twig file.
If you set a variable in your base file, in this case main.html.twig, then you can't overwrite it from inheriting templates.

Variables from child themes are accessible by their parents but get overriden as soon as you redeclare them in the parent.
So you can simply declare the variable in the parent only if is not defined:
{# main.html.twig #}
...
{% set body_class = body_class is defined ? body_class : '' %}
<body class="main {{ body_class }}">
...
{# dashboard.html.twig #}
{% extends 'main.html.twig' %}
{% set body_class = 'dashboard' %}

Related

Django templates inheritance

For example:
base.html
<body>
{% block content}
{% endblock %}
</body>
base_index.html
{% extends 'base.html' %}
{% block content %}
something
{% endblock %}
# add new block "for_child" to fill in with next inheritance
<h1>Name:
{% block for_child %}
{% endblock %}</h1>
base_index_child.html
{% extends 'base_index.html' %}
{% block for_child %}
Peter
{% endblock %}
Result base_index_child.html:
<body>
something
</body>
But i want (base.html -> base_index.html -> base_index_child.html)
<body>
something
<h1>Name: Peter</h1>
</body>
How to get this?
Update (answer)
Adding a block must be inside the block
base_index.html
{% extends 'base.html' %}
{% block content %}
something
<h1>Name:
{% block for_child %} # block must be inside the block
{% endblock %}</h1>
{% endblock %}
This post is pretty much what you're asking.
So this would fix it:
base_index.html
{% extends 'base.html' %}
{% block content %}
something
<h1>Name:
{% block for_child %}
{% endblock %}
</h1>
{% endblock %}

Django template tag content missing when extending admin app base template

So I am creating a page in my Django project that essentially just uses the Django admin app header and footer.
I have a template folder in the root of my project where I have my base.html.
/templates/admin/base.html
{% load i18n static %}<!DOCTYPE html>
{% load static %}
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{% static 'js-stack/assets/css/spark-styles.css' %}" />
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}" />
{% block extrastyle %}{% endblock %}
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}" />{% endif %}
{% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head>
{% load i18n %}
<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}"
data-admin-utc-offset="{% now "Z" %}">
<!-- Container -->
<div id="container">
{% if not is_popup %}
<!-- Header -->
<div id="header">
<div id="branding">
{% block branding %}{% endblock %}
</div>
{% block usertools %}
{% if has_permission %}
<div id="user-tools">
{% block welcome-msg %}
{% trans 'Welcome,' %}
<strong>{% firstof user.get_short_name user.get_username %}</strong>.
{% endblock %}
/ View Analytics /
{% block userlinks %}
{% if site_url %}
{% trans 'View site' %} /
{% endif %}
{% if user.is_active and user.is_staff %}
{% url 'django-admindocs-docroot' as docsroot %}
{% if docsroot %}
{% trans 'Documentation' %} /
{% endif %}
{% endif %}
{% if user.has_usable_password %}
{% trans 'Change password' %} /
{% endif %}
{% trans 'Log out' %}
{% endblock %}
</div>
{% endif %}
{% endblock %}
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
{% block breadcrumbs %}
<div class="breadcrumbs">
{% trans 'Home' %}
{% if title %} › {{ title }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block messages %}
{% if messages %}
<ul class="messagelist">{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
{% endfor %}</ul>
{% endif %}
{% endblock messages %}
<!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% block pretitle %}{% endblock %}
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
{% block content %}
{% block object-tools %}{% endblock %}
{{ content }}
{% endblock %}
{% block sidebar %}{% endblock %}
<br class="clear" />
</div>
<!-- END Content -->
{% block footer %}<div style="padding: 10px 40px;" id="footer"><img src="{% static 'wifispark-logo.png' %}"></div>{% endblock %}
</div>
<!-- END Container -->
</body>
</html>
So this is a copy of the admin app base.html, but with a few modificatio0ns such as an image in the footer. This is all working as expected when I log into the admin app.
I also have another app called 'analytics' inside my project. Below is the template for it where I have extended the admin/base.html.
{% extends "admin/base.html" %}
{% load static %}
{% block content %}
<div class="container-fluid">
</div>
{% endblock content %}
Now, when I view my analytics page it loads with all the expected header and footer styling from the admin/base.html, but there is content missing such as the admin app title and the menu links, both of which are pulled through from admin app template tags.
Can anyone shed any light on what I am doing wrong or am missing?
Many thanks,
James
In your View, the one that renders the analytics page make sure you pass user, site_header, has_permission, and site_url as parameters.
These parameters can be extracted like this:
from django.contrib.admin import AdminSite
class MyAdminSite(admin.AdminSite):
pass
mysite = MyAdminSite()
And then return them while rendering your template:
def get(self, request):
return render(request, 'analytics.html', {'user': request.user,'site_header': mysite.site_header,'has_permission': mysite.has_permission(request), 'site_url': mysite.site_url})
Hope that helps

Can't extend templates correctly - missing elements from parent template

I'm trying to create two tables which I want to be inside the Django admin. I know what template I have to extend but I can't figure out why there missing some elements. For example Logout, Welcome text etc. I want to have normal Django admin header there.
This is a regular django admin header - right side (with theme so there is greeen):
And this is the header of extended template:
I'm attaching my template and admin base.html:
{% extends "admin/base.html" %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block title %}
Admin Pairing
{% endblock %}
{% block extrahead ..... endblock %}
{% block branding %}{% trans "Pairing Rides" %}{% endblock %}
{% block content %}
<h2>{% trans "Candidate pair reservations" %}</h2>
<br>
{% render_table table %}
<hr>
<h2>{% trans "Existing pair reservations" %}</h2>
{% render_table table_existing %}
<div class="overlay">
<div id="loading-img"></div>
</div>
{% endblock %}
And this is the template I extend from:
{% load i18n admin_static %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}" />
{% block extrastyle %}{% endblock %}
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}" />{% endif %}
{% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head>
{% load i18n %}
<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}"
data-admin-utc-offset="{% now "Z" %}">
<!-- Container -->
<div id="container">
{% if not is_popup %}
<!-- Header -->
<div id="header">
<div id="branding">
{% block branding %}{% endblock %}
</div>
{% block usertools %}
{% if has_permission %}
<div id="user-tools">
{% block welcome-msg %}
{% trans 'Welcome,' %}
<strong>{% firstof user.get_short_name user.get_username %}</strong>.
{% endblock %}
{% block userlinks %}
{% if site_url %}
{% trans 'View site' %} /
{% endif %}
{% if user.is_active and user.is_staff %}
{% url 'django-admindocs-docroot' as docsroot %}
{% if docsroot %}
{% trans 'Documentation' %} /
{% endif %}
{% endif %}
{% if user.has_usable_password %}
{% trans 'Change password' %} /
{% endif %}
{% trans 'Log out' %}
{% endblock %}
</div>
{% endif %}
{% endblock %}
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
{% block breadcrumbs %}
<div class="breadcrumbs">
{% trans 'Home' %}
{% if title %} › {{ title }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block messages %}
{% if messages %}
<ul class="messagelist">{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
{% endfor %}</ul>
{% endif %}
{% endblock messages %}
<!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% block pretitle %}{% endblock %}
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
{% block content %}
{% block object-tools %}{% endblock %}
{{ content }}
{% endblock %}
{% block sidebar %}{% endblock %}
<br class="clear" />
</div>
<!-- END Content -->
{% block footer %}<div id="footer"></div>{% endblock %}
</div>
<!-- END Container -->
</body>
</html>
Why there is no such header in my case?
For example this:
<strong>{% firstof user.get_short_name user.get_username %}</strong>
There is condition {% if has_permission %} which should be True because I open this page using superusers account.
EDIT:
I've found out that has_permission is False. Can't figure out why.
i had the same problem a moment ago, the "has_permission" is a variable, pass then from view to template. ;)

Django template rendering extend tag incorrectly

I have three Django templates:
base.html:
user_links.html
user_detail.html
I want user_links.html to extend base.html. Next, I want user_detail.html to extend user_links.html and base.html.
Here's base.html:
<head>
<title>Cool App</title>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/main.css" />
</head>
<body>
<h1>Cool App</h1>
<div class="navbar">
<p>
HOME |
{% if user.is_authenticated %}
LOGOUT
{% else %}
LOGIN
{% endif %}</p>
{% block content %}
{% endblock %}
{% block pagination %}
{% endblock %}</div>
Here's user_links.html:
{% extends "base.html" %}
Yellow
Pink
Green
{% block content %}
{% endblock %}
And here's user_detail.html
{% extends "user_links.html" %}
{% block content %}
<h2>{{ object.username }}'s Profile</h2>
{% if object.userprofile.bio %}
{{ object.userprofile.bio }}
{% endif %}
{% endblock %}
So when the browser renders user_detail.html, I want it to (i) show the stylesheet and navigation links from base.html, (ii) show the word Yellow, Pink, Green from user_links.html, (iii) and show the user's username and bio. But (ii) is not being rendered at all, though (i) and (iii) are correctly rendering.
How should the templates be set up so that I see (i), (ii) and (iii) in user_detail.html? Please advise.
Note: all three templates reside in the same directory. I'm on Django 1.5
If you extends a base.html template, no content not surrounded by {% block %} will be rendered at all.
You could create additional {% block precontnet %}{% endblock %} in base.html, and wraps Pink/Yellow/Red in user_links.html
Or you can put Pink/Yellow/Red in {% block content %} if user_links.html and use {{ block.super }} in user_detail.html
links.html
{% extends "base.html" %}
{% block content %}
Yellow
Pink
Green
{% endblock %}
user_detail.html
{% extends "user_links.html" %}
{% block content %}
{{ block.super }}
<h2>{{ object.username }}'s Profile</h2>
{% if object.userprofile.bio %}
{{ object.userprofile.bio }}
{% endif %}
{% endblock %}
Place div after </p> in base.html
<h1>Cool App</h1>
<div class="navbar">
<p>
HOME |
{% if user.is_authenticated %}
LOGOUT
{% else %}
LOGIN
{% endif %}</p>
</div>
Try this in user_links.html
{% extends "base.html" %}
{% block content %}
Yellow
Pink
Green
{% endblock %}

Django templates - if statement before displaying a {% block %} tag not working properly?

This is my basic html page which my other html pages extend off of (it is called base.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Django Bookmarks | {% block title %}{% endblock %}</title>
<link rel='stylesheet' type='text/css' href='/site_media/css/style.css' />
</head>
<body>
{% block header %}
<p> signed in! </p>
{% endblock %}
{% block content %}{% endblock %}
</body>
</html>
Now, this is my main page.
{% extends "base.html" %}
{% block title %} Title {% endblock %}
{% if user.username %}
{% else %}
{% block header %}{% endblock %}
{% endif %}
{% block content %}
{% if user.username %}
<p>Welcome {{ user.username }}.</p>
{% else %}
<p>Not Signed in</p>
{% endif %}
{% endblock %}
as you can see, I want my
{% block header %}{% endblock %}
to be empty if no user is signed in, but if there is a user signed in, I want the
{% block header %}
to inherit from base.html. However, it does not inherit from base.html even when a user is signed in. The header block does not show when the user is signed in. Any idea why?
Use block.super:
{% block header %}
{% if user.username %}
{{ block.super }}
{% else %}
{# empty #}
{% endif %}
{% endblock %}
According to Django template documentation:
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. .....