How can I access a block from flask(not from template)? - python

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>

Related

Passing a variable to include in extends in Django templates

I have the following structure of templates:
main.html
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% include 'heading.html' with title=title %} {# but this does not work since it is not a variable #}
</body>
</html>
heading.html
<p>
{{ title }}
</p>
page.html
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
How can I pass the title from page.html to heading.html? Ideally, it should be defined as a block like now, but alternatives are also welcome. I'd like to contain the solution within the templates if possible.
Clarification:
This is a minimal example, but I have multiple pages like main.html that share a larger header that has title and some other variables that I'd like defined in the child template (not necessarily as variable as long as the text is passed).
I could put the title into the view code, but this solution would just decrease the separation of displayed data from the logic.
Use a block around the include with variables, and then wrap {{ block.super }} in the with template tag.
main.html:
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% block with_variables %}
{% include 'heading.html' %}
{% endblock %}
</body>
</html>
page.html:
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
{% block with_variables %}
{% with title="variable title" %}
{{ block.super }}
{% endwith %}
{% endblock %}
You may name it {% block heading %}, or nest the whole main.html in {% block content %}.
instead of {% include %}, you might want to use custom template tags with returning html or extension like slippers
You don't need heading.html. You can use the context variable title directly; as long as you pass it to your render function in your view, e.g.:
views.py
def my_view(request):
context = {'title': 'Hello World!'}
return render(request, 'page.html', context=context)
main.html
<html>
<body>
<p>
This is my title:
{% block title %}{% endblock %}
</p>
</body>
</html>
page.html
{% extends 'main.html' %}
{% block title %}
<strong>{{title}}</strong>
{% endblock %}
If you have administrative rights to your Django installation, an easy and elegant solution would be to switch your Django's template renderer to Jinja2 instead using django-jinja as a backend.
The main advantage of Jinja2 for the needs of this question is that it supports assignment of a block to a variable through block assignments. Since Jinja2 is inspired by the Django template language, your existing templates will need few modifications, if any.
With Jinja2 as a template renderer, you can set the title variable with a block of HTML content in the child template:
page.html
{% extends 'main.html' %}
{% set title %}test title{% endset %}
The title variable will then work in the shared template:
main.html
<html>
<body>
<p>
Main template works: {{ title }}
</p>
{% include 'heading.html' %}
</body>
</html>
And it will also work in the included template:
heading.html
<p>
Included template also works: {{ title }}
</p>
Demo: https://replit.com/#blhsing/AlarmedCleverDebugmonitor
One possible solution is to split heading.html into two and add a {% block %} in-between, but this is an ugly workaround that is prone to bugs with unclosed tags.
I am searching for a better alternative.
main.html
...
{% include 'heading1.html' %} {# containing <p> #}
{% block title %}{% endblock %}
{% include 'heading2.html' %} {# containing </p> #}
...
Additionally, if white spaces are important, there has to be no new line between includes and the block.
add your title to the rendering context and it will be visible in page, main and included heading.

How to chain {% includes %} in django templating

I have a base.html file that looks like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
{% block header %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
{% block footer %}{% endblock %}
</body>
</html>
and I have a file, auth.html that extends this:
{% extends "base.html" %}
{% block content %}
[MY CONTENT]
{% endblock %}
which works fine, but I also want to have a separate header.html file that plugs into the header block above.
What's the correct way to structure auth.html and header.html in order to include both and to have both extend base.html?
I tried adding a {% include header.html %} line to auth.html, and structuring header.html as follows:
{% extends "base.html" %}
{% block header %}
[HEADER CONTENT HERE]
{% endblock %}
but that didn't work. How should I be doing this?
You need {{ block.super }}:
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.
Its burried in the template inheritance documentation.
Suppose you want to add extra stuff to the header block in auth.html. header is defined in index.html:
Your auth.html would look like:
{% extends "index.html" %}
{% block header %}
{{ block.super }}
Your extra stuff, which will come after whatever was in the header block
{% 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

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