Inherit template without using super() - python

I have the following base.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<link rel = "stylesheet" href = "{{ url_for('static', filename = 'css/base.css') }}" type = "text/css"/>
{% block head %}
{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
Then I have base_header.html, which I want for pages with a header
{% extends "base.html" %}
{% block head %}
<link rel = "stylesheet" href = "{{ url_for('static', filename = 'css/header.css') }}" type = "text/css"/>
{% endblock %}
{% block content %}
<header>
...
</header>
{% endblock %}
In order for the header to show up, I have to call super() in both blocks
{% extends "base_header.html" %}
{% block head %}
{{ super() }}
<title>Page title</title>
{% endblock %}
{% block content %}
{{ super() }}
<h1>Page header</h1>
{% endblock %}
Is it possible to have this sort of template inheritance without having to include super() every time I want to include the header? I would like it so if I decide a page needs a header, I can just change extends "base.html" to extends "base_header.html" without further changes.

You need the super() call, because otherwise your final template is replacing the content of the head block in the parent template. You could introduce a new block in the intermediate template, base_header.html:
{% block head %}
<link rel = "stylesheet" href = "{{ url_for('static', filename = 'css/header.css') }}" type = "text/css"/>
{% block more_head %}
{% endblock %}
{% endblock %}
Then your final template looks like:
{% extends "base_header.html" %}
{% block more_head %}
<title>Page title</title>
{% endblock %}

Related

Django : Register or load { % block content % } tag in HTML

I am trying to extend my templates .
base_layout.html:
{% load static from staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Articles</title>
<link rel = "stylesheet" href = "{% static 'styles.css' %}">
</head>
<body>
<div class="wrapper">
{% block content %}
{% endblock %}
</div>
</body>
</html>
article_list.html:
{% extends 'base_layout.html' %}
{% block content %}
<h1>Article List</h1>
<div class = "articles">
{% for article in articles %}
<div class = "article">
<h2>{{ article.title}}</h2>
<p>{{ article.body }}</p>
<p>{{ article.date }}</p>
</div>
{% endfor %}
</div>
{% endblock %}
When i run this i am getting the error like this:
django.template.exceptions.TemplateSyntaxError: Invalid block tag on line 11: 'blockcontent'. Did you forget to register or load this tag?
What mistake am i doing?

Python Panel Template change the Title from Bokeh Application to MyApp

I am running the example https://panel.pyviz.org/user_guide/Templates.html and would like to change the title from "Bokeh Application" to "My App".
import panel as pn
import holoviews as hv
from jinja2 import Environment, FileSystemLoader
pn.extension()
env = Environment(loader=FileSystemLoader('.'))
jinja_template = env.get_template('z_base.html')
tmpl = pn.Template(jinja_template)
tmpl.add_panel('A', hv.Curve([1, 2, 3]))
tmpl.add_panel('B', hv.Curve([1, 2, 3]))
tmpl.show();
with html z_base.html extending base:
{% extends base %}
<title>{% block title %}My App{% endblock %}</title> <!-- THIS DOES NOT WORK !!!! -->
{% block postamble %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
{% endblock postamble %}
{% block contents %}
<h1>Custom Template App 3</h1>
<p>This is a Panel app with a custom template allowing us to compose multiple Panel objects into a single HTML document.</p>
<br>
<div class="container">
<div class="row">
<div class="col-sm">
{{ embed(roots.A) }}
</div>
<div class="col-sm">
{{ embed(roots.B) }}
</div>
</div>
</div>
{% endblock %}
base template refer to the
title <title>{% block title %}{{ title | e if title else "Panel App" }}{% endblock %}</title>
<!DOCTYPE html>
<html lang="en">
{% block head %}
<head>
{% block inner_head %}
<meta charset="utf-8">
<title>{% block title %}{{ title | e if title else "Panel App" }}{% endblock %}</title>
{% block preamble %}{% endblock %}
{% block resources %}
{% block css_resources %}
{{ bokeh_css | indent(8) if bokeh_css }}
{% endblock %}
{% block js_resources %}
{{ bokeh_js | indent(8) if bokeh_js }}
{% endblock %}
{% endblock %}
{% block postamble %}{% endblock %}
{% endblock %}
</head>
How can I pass the title variable to the base template?
I had the same need and couldn't find an answer anywhere on the documentation. Your question here helped guide me, so I wanted to report the simple solution I've found.
I ended up going through the panel.template module code and API doc to look for hints. It turns out you can pass your custom title to the servable or show methods. In your code, it would look like this:
tmpl.show(title="My App");
I've tested it with both servable and show methods.
#EMayorga answer didn't work, but I think what is intended is to extend and implement that block. I got it to work from doing this in my template:
{% extends base %}
{% block title %}
{{ html_title }}
{% endblock %}
<!-- goes in body -->
{% block postamble %}
<link rel="stylesheet" href="https://stackpath.bootstrapcd ...
...
And then in python: tmpl.add_variable('html_title', 'Demo 23')

How to access context variables in parents template django

I have base.html and file with header _header_main.html in my main template index.html i extends base.html and include _header_main.html but variables that i pass into index.html not visible in parent template
base.html:
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<!-- styles -->
...
</head>
<body>
{% block _header_main %}{% endblock %}
{% block _header_mobile %}{% endblock %}
<div class="wrapper">
<!-- header -->
{% block header_main %}{% endblock %}
{% block header_mobile %}{% endblock %}
<div class="after_header"></div>
<!-- end header -->
{% block content %}{% endblock %}
<footer class="footer">
...
</footer>
</div>
</body>
</html>
_header_main.html:
<header class="header">
<ul>
{% for i in servers %}
<li>{{ i.title }}</li>
{% endfor %}
</ul>
</header>
index.html:
{% extends "base.html" %}
{% load static %}
{% block title %}Title{% endblock %}
{% block header_main %}
{% include "_header_main.html" %}
{% endblock %}
{% block content %}
Some content...
{% endblock %}
<scripts>
...
</scripts>
How i can access to variables items in my template?
Edit. My function in views.py
def index(request):
servers = Server.objects.all().order_by('ranking')
basket_count, total_price = basket_calculate(request)
server_arr = [i.title for i in servers]
servers_string = ', '.join(server_arr)
return render(request, 'index.html', {'servers':servers, 'temp_year' : datetime.now().year,
'basket_count':basket_count, 'total_price':total_price,
'servers_string':servers_string })
The reason why my items variable don't show in templates, is because i add <script> tag with js without block, so my scripts didn't work. I add my scripts to {% block script %} and all works fine!

How to modularize templates in django?

base.html
<!DOCTYPE html>
<html>
<head>
{% block head %}
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
head.html
<title>Example</title>
body.html
<h1>Example Django</h1>
Using django, you can render the template "base.html" but replace the blocks "head" and "body", respectively, by templates "head.html" and "body.html"?
If i understand you right, you need include tag
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
<!DOCTYPE html>
<html>
<head>
{% include "head.html" %}
</head>
<body>
{% include "body.html" %}
</body>
</html>
{% include "base.html" %}
{% block head %}
{% include "head.html" %}
{% endblock %}
{% block body %}
{% include "body.html" %}
{% endblock %}

Is there a way to pass variables into Jinja2 parents?

I'm trying to pass some variables from the child page to the template. This is my python code:
if self.request.url.find("&try") == 1:
isTrying = False
else:
isTrying = True
page_values = {
"trying": isTrying
}
page = jinja_environment.get_template("p/index.html")
self.response.out.write(page.render(page_values))
The template:
<html>
<head>
<link type="text/css" rel="stylesheet" href="/css/template.css"></link>
<title>{{ title }} | SST QA</title>
<script src="/js/jquery.min.js"></script>
{% block head %}{% endblock head %}
</head>
<body>
{% if not trying %}
<script type="text/javascript">
// Redirects user to maintainence page
window.location.href = "construct"
</script>
{% endif %}
{% block content %}{% endblock content %}
</body>
</html>
and the child:
{% extends "/templates/template.html" %}
{% set title = "Welcome" %}
{% block head %}
{% endblock head %}
{% block content %}
{% endblock content %}
The problem is, I want to pass the variable "trying" into the parent, is there a way to do this?
Thanks in advance!
The example on the Jinja2 Tips and Tricks page explains this perfectly, http://jinja.pocoo.org/docs/templates/#base-template. Essentially, if you have a base template
**base.html**
<html>
<head>
<title> MegaCorp -{% block title %}{% endblock %}</title>
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
</body>
</html>
and a child template
**child.html**
{% extends "base.html" %}
{% block title %} Home page {% endblock %}
{% block content %}
... stuff here
{% endblock %}
whatever python function calls render_template("child.html") will return the html page
**Rendered Page**
<html>
<head>
<title> MegaCorp - Home page </title>
</head>
<body>
<div id="content">
stuff here...
</div>
</body>
</html>
I think that you are looking to highlight active menus in the base layout and you need something like this
{% extends 'base.html' %}
{% set active = "clients" %}
then use can use "active" inside base.html
You just need to declare that variable before extending the template, so the extended template will have access to to the variable trying
{% set trying = True %} <----------- declare variable
{% extends "/templates/template.html" %}
{% set title = "Welcome" %}
{% block head %}
{% endblock head %}
{% block content %}
{% endblock content %}
Few years later but hoping it may help latecomers
I do not understand your problem. When you pass variables to the context (as you do with trying) these variables will be available in the child and the parent.
To pass title to the parent, you have to use inheritance, sometimes in combination with super : http://jinja.pocoo.org/docs/templates/#super-blocks
See also this question: Overriding app engine template block inside an if

Categories

Resources