I have 4 files:
flask_blog.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
@app.route("/home")
def home_page():
return render_template("home.html")
@app.route("/about")
def about():
return render_template("about.html", title = "About")
layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>Flask Blog - {{ title }}</title>
{% else %}
<title>Flask Blog</title>
{% endif %}
</head>
<body>
{% block content %}{% endblock content %}
</body>
</html>
home.html
{% extends "layout.html" %}
{% block content %}{% endblock content %}
about.html
{% extends "layout.html" %}
{% block content %}{% endblock content %}
On my about page, the title is "Flask Blog - About", and in my home page, the title is "Flask blog". Now, this is happening due to the if/else statements in the layout.html file. The if/else statements are:
{% if title %}
<title>Flask Blog - {{ title }}</title>
{% else %}
<title>Flask Blog</title>
{% endif %}
Now, the value of the 'title' variable must be 0 or None, since we are going to the else statement for the home page. Now, my question is, we didn't assign a value to the 'title' variable beforehand. Better yet, we haven't even created the 'title' variable in the flask_blog.py file. How are we not getting a NameError? Shouldn't we get NameError: name 'title' is not defined
?
CodePudding user response:
The templating language used by default in flask is Jinja. Jinja is not Python, and as such it works a little differently sometimes.
When a variable is not defined, if
statements in Jinja template evaluate to False
. As a result it doesn't throw an exception but instead it just goes to the next else
block.
More specifically, an undefined variable becomes of type Undefined
, which has it's own documentation page: https://jinja.palletsprojects.com/en/3.1.x/api/#undefined-types
This is useful in a templating language, because it makes it easier to re-use complex templates without having to specify every parameter every time you render it. If a parameter (and corresponding if block) is not relevant for a call to render_template, you can just omit it and don't worry about it.