Is there a way to pass variables into Jinja2 parents? - python

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

Related

Inherit template without using super()

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

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 can I access a block from flask(not from template)?

here's my generalized question:
base.html :
<html>
<head>
{% if title %}
<title>{{title}}</title>
{% else %}
<title>test</title>
{% endif %}
</head>
<body>
{% block content %} {% endblock %}
</body>
</html>
How can I write a function that can directly create a block? maybe something like:
#app.route("/foo")
def foo():
content = "<h1>this is foo page</h1>"
return render_html("base.html", content = content)
You are trying to render HTML in your Jinja2 template without HTML escaping. By default, Jinja2 is configured to do automatic escaping of all variables you interpolate.
This means that
<h1>this is foo page</h1>
is actually rendered as
<h1>this is foo page</h1>
so you don't accidentally use HTML in your pages where you didn't mean to. This is very important to protect against Cross Site Scripting (XSS) attacks.
If you are going to bypass this automatic escaping, and deliberately insert HTML into your templates, you must make sure you know what you are doing - never allow unescaped user input to get into these variables.
With the background lesson and security warnings out of the way, if you do know what you are doing, you can explicitly mark values as "safe" in your template, so they will not be escaped. Just use Jinja2's builtin filter, safe, like so:
<body>
{{ content | safe }}
</body>
In your case, I think you also wanted to have a block, so you can override with template inheritance. For an example of that, play with this complete example app
test.py:
import flask
app = flask.Flask(__name__)
#app.route("/foo")
def foo():
content = "<h1>this is foo content</h1>"
return flask.render_template("base.html", content=content)
#app.route("/bar")
def bar():
content = "<h1>this is bar content</h1>"
return flask.render_template("child.html", content=content)
if __name__ == "__main__":
app.run(debug=True)
templates/base.html:
<html>
<head>
{% if title %}
<title>{{title}}</title>
{% else %}
<title>test</title>
{% endif %}
</head>
<body>
{% block content %}{{ content | safe }}{% endblock %}
</body>
</html>
templates/child.html:
{% extends "base.html" %}
{% block content %}
{{ super() }}
<h2>And this bit comes from the child template</h2>
{% endblock %}
view :
#app.route("/foo")
def foo():
content = "<h1>this is foo page</h1>"
return render_template("base.html", content = content)
base.html:
<html>
<head>
{% if title %}
<title>{{title}}</title>
{% else %}
<title>test</title>
{% endif %}
</head>
<body>
{% block content %}
{% if content %}
{{ content | safe }}
{% else %}
No content provided
{% endif %}
{% endblock %}
</body>
</html>

How to parse a django template and render specific tag

Is it possible to parse a django template and only render a specific tag ?
This snippet is close to what I'm looking for but it doesn't return the entire template.
Basically if I have this template as input
<html>
<title>{% block title%}{% endblock %}</title>
<body>
{% block content %}
{% mycustomtag "args" %}
{% endblock content %}
</body>
</html>
and i want to only render mycustomtag this is the output Im looking for
<html>
<title>{% block title%}{% endblock %}</title>
<body>
{% block content %}
<p>Result from mycustomtag</p>
{% endblock content %}
</body>
</html>
Thanks.
If I properly understand your question, then there is a way to do that, using the {% verbatim %} tag. It will be added in Django 1.5, but for now you can use it as your custom tag - here is the source: https://code.djangoproject.com/ticket/16318
The only drawback here is that you cannot use directly this template, it needs double rendering. If this is what you need - then everything is OK.
To use it, all you need to do is to enclose the other tags with {% verbatim %} :
{% load my_custom_tags %} <-- this is needed to load the 'verbatim' and 'mycustomtag' tags
{% verbatim %}
<html>
<title>{% block title%}{% endblock %}</title>
<body>
{% block content %}
{% endverbatim %}
{% mycustomtag "args" %}
{% verbatim %}
{% endblock content %}
</body>
</html>
{% endverbatim %}
I've made a simple test with this template:
#register.simple_tag
def mycustomtag(a):
return "<p>%s</p>" % a
....
from django.template import loader, Context
print loader.get_template("test.html").render(Context({}))
This prints the following:
<html>
<title>{%block title%}{%endblock%}</title>
<body>
{%block content%}
<p>args</p>
{%endblock content%}
</body>
</html>
Hope this could be helpful.

Django templates: overriding blocks of included children templates through an extended template

I'm wondering if anyone knows how to deal with the following quirky template structure:
### base.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title> {% block title %} Title of the page {% endblock %} </title>
</head>
<body>
<header>
{% block header %}
{% include "base/header.html" %}
{% endblock header %}
</header>
{% block content %}{% endblock %}
</body>
</html>
### base/header.html
<div id="menu-bar">
{% block nav %}
{% include "base/nav.html" %}
{% endblock %}
</div>
### base/nav.html
<nav id="menu">
<ul>
<li>
My Profile
</li>
<li>
My Favorites
</li>
{% block extra-content %}{% endblock %}
</ul>
</nav>
And, the heart of the matter:
### app/somepage.html
{% extends "base.html" %}
{% block content %}
<p>Content is overridden!</p>
{% endblock %}
{% block extra-content %}
<p>This will not show up, though...</p>
{% endblock %}
{% block nav %}
<p>Not even this.</p>
{% endblock %}
The problem is when extending a template you can only override the blocks declared in the parent only, not any of its children.
I suppose I could make base.html a husk of empty unused nested blocks covering all future contingencies, but would even that override properly? And is that the only way?
If you're wondering why I have a bi-directional include/extends workflow around base.html, I have many sub-templates that I want to get used all across the project: Headers, footers, navs, sidebars, etc. They all will be consistant in structure across the entire site, but in many cases a whole subdivision of the site will only need a few of those sub-templates. My idea was to define the sub-templates under the templates/base folder, and have templates/base-type1.html, templates/base-type2.html, etc to extend in other places. Each type would only reference the sub-templates needed, and override them to place content as needed.
It seems to be little known that you can use the with keyword with the include to pass variables into the context of an included template - you can use it to specify includes in the included template:
# base.html
<html>
<body>
{% block header %}{% include "header.html" %}{% endblock %}
</body>
</html>
# header.html
# some stuff here
<div id="header">
<img src="logo.png">
{% include nav_tmpl|default:"navigation.html" %}
</div>
# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
{% include "header.html" with nav_tmpl="special_nav.html" %}
# you might also want to wrap the include in an 'if' tag if you don't want anything
# included here per default
{% endblock %}
This approach saves you at least from having one additional file just for the purpose of overwriting a block. You can also use the with keyword to pass a value through a bigger hierarchy of includes as well.
A terser variant to the solution proposed by #Bernhard Vallant:
# base.html
<html>
<body>
{% block header %}{% include "header.html" %}{% endblock %}
</body>
</html>
# header.html
# some stuff here
<div id="header">
<img src="logo.png">
{% include nav_tmpl|default:"navigation.html" %}
</div>
# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
{% with nav_tmpl="special_nav.html" %}
{{ block.super }}
{% endwith %}
{% endblock %}
You can solve this by extending your currently-included templates, then including the extension instead of the the currently-included base template.

Categories

Resources