Getting Started with Flask Templates: Jinja2 Variables and Control Structures

In Flask web application development, how to dynamically display data on a page? This is where Flask’s template system comes into play. Flask natively uses the Jinja2 templating engine to handle dynamic content, allowing you to embed variables and control logic directly in HTML, making your pages “come alive.” Today, we’ll start by learning the basics of Jinja2 variables and control structures in Flask templates.

1. Jinja2 Variables: Injecting Dynamic Data into Pages

Jinja2 variables are the foundation of dynamic content in templates, enabling you to render data passed from the backend into the page.

1.1 Defining and Using Variables

To use variables in a template, first pass data from your Flask view function to the template using render_template, then render the variables with {{ variable_name }}.

Example:
Suppose you want to pass user information (name, age, hobbies) to a template.

Step 1: View Function (Backend)
In app.py, define the view function and pass variables:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    # Define variables to pass to the template
    user_name = "小明"
    user_age = 18
    hobbies = ["篮球", "编程", "阅读"]
    return render_template('index.html', 
                          name=user_name, 
                          age=user_age, 
                          hobbies=hobbies)  # Pass variables to the template

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

Step 2: Template File (Frontend)
Create index.html in the templates folder and render variables with {{ variable_name }}:

<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<body>
    <h1>欢迎!{{ name }}的个人页面</h1>  <!-- Render string variable -->
    <p>你的年龄是:{{ age }}岁</p>         <!-- Render number variable -->
    <h2>你的爱好:</h2>
    <ul>
        <!-- Remember this for loop; we'll cover it later -->
        {% for hobby in hobbies %}
            <li>{{ hobby }}</li>
        {% endfor %}
    </ul>
</body>
</html>

Result: The page will display:
- “欢迎!小明的个人页面”
- “你的年龄是:18岁”
- A list of hobbies.

1.2 Variable Types and Common Operations

Jinja2 supports various data types (strings, numbers, lists, dictionaries) with intuitive operations:

  • Strings: Directly rendered, supporting filters (covered later).
  • Numbers: Can participate in basic arithmetic (e.g., addition, subtraction).
  • Lists: Iterated using for loops (see next section).
  • Dictionaries: Accessed via key or dict.key, or iterated with dict.items().

Dictionary Example:
If you pass user_info = {"city": "北京", "hobby": "跑步"} from the backend:

<p>居住城市:{{ user_info.city }}</p>  <!-- Direct key access -->
<p>爱好:{{ user_info.hobby }}</p>
<!-- Iterate over key-value pairs -->
{% for key, value in user_info.items() %}
    <p>{{ key }}:{{ value }}</p>
{% endfor %}

2. Control Structures: Making Pages “Logical”

With variables, control structures (e.g., conditionals, loops) enable flexible data display.

2.1 Conditional Statements: if-else

Use {% if ... %} to conditionally render content:

Example: Show different messages based on age:

{% if age >= 18 %}
    <p>你已成年,可访问更多内容!</p>
{% else %}
    <p>你还是未成年人,请注意安全上网哦~</p>
{% endif %}

Extended: Use elif for multiple conditions:

{% if age < 10 %}
    <p>幼儿</p>
{% elif age < 18 %}
    <p>青少年</p>
{% else %}
    <p>成年人</p>
{% endif %}

2.2 Loops: for Loops

Use {% for ... in ... %} to iterate over lists or dictionaries:

Example 1: Iterate over a list (e.g., hobbies):

<ul>
    {% for hobby in hobbies %}
        <li>{{ hobby }}</li>
    {% endfor %}
</ul>

Example 2: Special Loop Variable loop
Jinja2 provides loop to access iteration metadata:
- loop.first: First iteration (boolean).
- loop.last: Last iteration (boolean).
- loop.index: Current index (starts at 1).

Optimized Hobbies List:

<ul>
    {% for hobby in hobbies %}
        {% if loop.first %}
            <li><strong>第一个爱好:</strong>{{ hobby }}</li>
        {% elif loop.last %}
            <li><strong>最后一个爱好:</strong>{{ hobby }}</li>
        {% else %}
            <li>{{ loop.index }}. {{ hobby }}</li>
        {% endif %}
    {% else %}
        <!-- Display if the list is empty -->
        <li>暂无爱好数据</li>
    {% endfor %}
</ul>

3. Simple Filters: Processing Variables

Filters modify variables using |filter_name syntax (e.g., formatting, case conversion).

Common Filters:

  • String Manipulation:
  • upper: Convert to uppercase
    {{ name|upper }} → “XIAOMING” (if name = "小明")
  • lower: Convert to lowercase
    {{ "Hello"|lower }} → “hello”
  • capitalize: Capitalize first letter
    {{ "hello"|capitalize }} → “Hello”

  • Number Manipulation:

  • int: Convert to integer
    {{ 18.5|int }} → “18”
  • round: Round to nearest integer
    {{ 3.1415|round }} → “3”

  • Safety: Render HTML content with |safe (use only with trusted data):
    {{ "<p>这是一段HTML</p>"|safe }} → Renders as <p>这是一段HTML</p>

4. Summary

With Jinja2 variables and control structures, you can dynamically display data and make pages logic-driven. Key takeaways:
- Variables: Use {{ variable_name }} to render data (strings, numbers, lists, dictionaries).
- Control Structures: {% if ... %} (conditionals) and {% for ... %} (loops), with loop for iteration metadata.
- Filters: Use |filter to modify variables (e.g., case conversion, formatting).

Next, we’ll explore advanced topics like template inheritance and macros to structure pages more cleanly. Try combining variables, conditionals, and loops in your own templates to make them “dynamic”!

Xiaoye