Jinja

Jinja is a web template engine for python. Jinja lets variables, statements in html file and can split files not to repeat html code. Jinja templates are just .html file that we will render from flask later. Flask render_template method will generate jinja templates into HTML file and return to client side.

Why Flask render Jinja templates instead of returning html text

When we return simple text with flask return statement, we need to escape user input value to protect injection attacks.

Below code will show input name from url without escaping

@app.route("/<name>")
def home(name):
return f"Hello, {name}"

Without escape code will work when user gave string or number or some datatype. But you pass some script like this as input

http://127.0.0.1:5000/<a href=”javascript:alert(‘unsafe’);”>click here

click here</a>your home route will show Hello click here because script work in browser. then you click you will see javascript alert with unsafe text.

So we need to escape those script to string. escape() from markupsafe python module escape those script into string. You can test the code below and go to this route again

http://127.0.0.1:5000/<a href=”javascript:alert(‘unsafe’);”>click here

from markupsafe import escape@app.route("/<name>")
def home(name):
return f"Hello, {escape(name)}"

escape function escape html a tag into string. input javascript doesn’t work on browser. Jinja templates automatically escape and we can use Jinja templates with flask render_template().

documentation

how to use?

Install Jinja2

pip install Jinja2

A Jinja template doesn’t need to have a specific extension: .html, .xml, or any other extension is just fine. documentation

Limiters

you can use variables, statements and comments.

Variable

{{    }}

Statement

{%    %}

Comment

{#   #}

Create main.py and templates and test below code

Variable pass to Jinja

<h2>{{ name }}</h2>
<h2>{{ email }}</h2>

main.py

from flask import Flask, render_template

app = Flask(__name__)

# creating route
@app.route("/")
def home():
return render_template("home.html", name='Sophia', email="sophia@gmail.com")

if __name__ == "__main__":
app.run(debug=True)

home.html

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h2>{{ name }}</h2>
<h2>{{ email }}</h2>
</body>
</html>

Output

For loop in Jinja

Example

<ul>
{% for color in colors %}
<li> {{color}} </li>
{% endfor %}
</ul>

Change html and main.py as above

If statement in Jinja

Example

{% if name == 'James' %}
<h1> {{name}} </h1>
{% endif %}

Change html and main.py as above

if else statement

Example

{% if name == 'James' %}
<h1>{{ name }}</h1>
{% else %}
<h1>not James</h1>
{% endif %}

Change html and main.py as above

Template Inheritance

documentation

block tag

{% block head %}{% endblock %}

super tag

{{ super() }}

Base Template

create base.html in templates

base.html

<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
&copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>

Child Template

home.html

{% extends "base.html" %}{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>{{self.title()}}</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
  • extends base template
  • create block tag from base.html and extends html css code
  • super tag in head block will give the result from parent template(base.html)

Connect with Bootstrap

connect with bootstrap is easy. link the bootstrap cdn in base.html as follow

base.html

<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<title>{% block title %}{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
{% endblock %}
</head><body>
{% block content %}
<h1>helo</h1>
{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js" integrity="sha384-eMNCOe7tC1doHpGoWe/6oMVemdAVTMs2xqW4mwXrXsW0L84Iytr2wi5v2QjrP/xp" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous">
</script>
</body>
</html>

home.html

{% extends "base.html" %}{% block title %}
My Website
{% endblock %}
{% block content %}
<div class="alert alert-primary" role="alert">
A simple primary alert—check it out!
</div>
<div class="alert alert-secondary" role="alert">
A simple secondary alert—check it out!
</div>
{{ super() }}
{% endblock %}

Url For

example

<a href="{{url_for('add')}}">go to add page</a>

main.py

from flask import Flask, render_template

app = Flask(__name__)

# creating route
@app.route("/")
def home():
return render_template("home.html", name="Jo")

@app.route("/add")
def add():
return render_template("add.html")

if __name__ == "__main__":
app.run(debug=True)

home.html

<body>
<a href="{{url_for('add')}}">go to add page</a>
</body>

Flash messages

Flash messages use to show error messages in jinja templates. Especially in login and register to show user error messages (eg, incorrent password, lastname required)

flash("incorrect password")

main.py

from flask import Flask, render_template, flash, request@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user = User.query.filter_by(email=request.form['email']).first()
if user:
if check_password_hash(user.password, request.form['password']):
login_user(user)
return redirect(url_for("secrets"))
else:
flash("incorrect password")
else:
flash("not found email")
return render_template("login.html")

login.html

{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

--

--

Cho Zin Thet
Cho Zin Thet

Written by Cho Zin Thet

Learning javascript and web-development

No responses yet