SoFunction
Updated on 2025-05-04

Detailed explanation of the use of Flask templates in Python and advanced techniques

1. Basics of template rendering

1.1 Why you need a template engine

In web development, writing HTML code directly in Python files will cause many problems:

  • The code is difficult to maintain
  • Severe front and back end coupling
  • Unable to reuse HTML components
  • Lack of logical control

Flask has built-in Jinja2 template engine, which perfectly solves these problems.

1.2 First template rendering example

First create the project structure:

myapp/
├──
└── templates/
    └──

content:

from flask import Flask, render_template

app = Flask(__name__)

@('/')
def index():
    user = {'username': 'Zhang San', 'age': 25}
    posts = [
        {'title': 'The first article', 'content': 'Content 1'},
        {'title': 'Part 2', 'content': 'Content 2'}
    ]
    return render_template('', user=user, posts=posts)

if __name__ == '__main__':
    (debug=True)

templates/content:

<!DOCTYPE html>
<html>
<head>
    <title>{{  }}Home page</title>
</head>
<body>
    <h1>welcome, {{  }}!</h1>
    <p>age: {{  }}</p>
    
    <h2>Article list</h2>
    <ul>
        {% for post in posts %}
        <li>{{  }} - {{  }}</li>
        {% endfor %}
    </ul>
</body>
</html>

1.3 Template Rendering Principle

Workflow of render_template() function:

  • Find the specified template file in the templates directory
  • Analyze variables and logic in templates
  • Pass context variables into template
  • Generate the final HTML response

2. Template access object properties

2.1 Access dictionary properties

<p>username: {{ user['username'] }}</p>
<p>age: {{ ('age', 18) }}</p>  <!-- With default value -->

2.2 Accessing object properties

Suppose we have a User class:

class User:
    def __init__(self, username, email):
         = username
         = email

You can access the template like this:

<p>username: {{  }}</p>
<p>Mail: {{  }}</p>

2.3 Access lists and tuples

<p>First article: {{ posts[0].title }}</p>
<p>Last article: {{ posts[-1].title }}</p>

2.4 Special variable access

<p>Current time: {{  }}</p>  <!-- accessFlaskConfiguration -->
<p>Request method: {{  }}</p>  <!-- access请求对象 -->
<p>Session information: {{ ('user_id') }}</p>
<p>Flash message: {{ get_flashed_messages() }}</p>

3. Use of filters

3.1 Complete collection of built-in filters

Jinja2 provides a wealth of built-in filters:

<!-- String processing -->
<p>{{ "hello"|capitalize }}</p>  <!-- Hello -->
<p>{{ "HELLO"|lower }}</p>  <!-- hello -->
<p>{{ "hello world"|title }}</p>  <!-- Hello World -->
<p>{{ "hello"|replace("e", "a") }}</p>  <!-- hallo -->

<!-- List processing -->
<p>{{ [1,2,3]|length }}</p>  <!-- 3 -->
<p>{{ [1,2,3]|first }}</p>  <!-- 1 -->
<p>{{ [1,2,3]|last }}</p>  <!-- 3 -->
<p>{{ [1,2,3]|join("|") }}</p>  <!-- 1|2|3 -->

<!-- Numerical processing -->
<p>{{ 3.1415926|round(2) }}</p>  <!-- 3.14 -->
<p>{{ 1000|filesizeformat }}</p>  <!-- 1000 Bytes -->
<p>{{ 0.85|float }}</p>  <!-- 0.85 -->

<!-- Date processing -->
<p>{{ user.create_time|datetimeformat }}</p>
<p>{{ user.create_time|datetimeformat('%Y-%m-%d') }}</p>

<!-- HTMLdeal with -->
<p>{{ "<script>alert(1)</script>"|escape }}</p>
<p>{{ "Markdown text"|markdown }}</p>
<p>{{ ""|urlencode }}</p>

3.2 Custom filters

Register custom filters in:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

@app.template_filter('format_phone')
def format_phone(phone):
    return f"{phone[:3]}-{phone[3:7]}-{phone[7:]}"

Used in templates:

<p>{{ "hello"|reverse }}</p>  <!-- olleh -->
<p>{{ "13812345678"|format_phone }}</p>  <!-- 138-1234-5678 -->

Advanced Tips for Flask Template

1. Control statements

Conditional judgment

{% if  &lt; 18 %}
    &lt;p&gt;Minor users&lt;/p&gt;
{% elif  &gt; 60 %}
    &lt;p&gt;Elderly users&lt;/p&gt;
{% else %}
    &lt;p&gt;Adult user&lt;/p&gt;
{% endif %}

Loop statement

&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Serial number&lt;/th&gt;
            &lt;th&gt;title&lt;/th&gt;
            &lt;th&gt;content&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        {% for post in posts %}
        &lt;tr class="{{ ('odd', 'even') }}"&gt;
            &lt;td&gt;{{  }}&lt;/td&gt;
            &lt;td&gt;{{  }}&lt;/td&gt;
            &lt;td&gt;{{  }}&lt;/td&gt;
        &lt;/tr&gt;
        {% else %}
        &lt;tr&gt;
            &lt;td colspan="3"&gt;No article yet&lt;/td&gt;
        &lt;/tr&gt;
        {% endfor %}
    &lt;/tbody&gt;
&lt;/table&gt;

Circular variable description:

  • : Current number of iterations (starting from 1)
  • loop.index0: Current number of iterations (starting from 0)
  • : Number of reverse iterations
  • : Whether it is the first iteration
  • : Whether it last iteration
  • : Sequence length

Macro definition (template function)

Defining macros:

{% macro render_comment(comment) %}
&lt;div class="comment"&gt;
    &lt;p&gt;{{  }} explain:&lt;/p&gt;
    &lt;blockquote&gt;{{  }}&lt;/blockquote&gt;
&lt;/div&gt;
{% endmacro %}

Using macros:

{{ render_comment(comment) }}

&lt;!-- Import macros from other templates --&gt;
{% from '' import render_comment %}

2. Template inheritance

Basic template()

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;{% block title %}Default title{% endblock %}&lt;/title&gt;
    {% block head %}
    &lt;link rel="stylesheet" href="{{ url_for('static', filename='') }}" rel="external nofollow" &gt;
    {% endblock %}
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="container"&gt;
        {% block content %}
        &lt;h1&gt;Default content&lt;/h1&gt;
        {% endblock %}
    &lt;/div&gt;
    
    {% block footer %}
    &lt;footer&gt;
        &lt;p&gt;&amp;copy; 2023 My App&lt;/p&gt;
    &lt;/footer&gt;
    {% endblock %}
&lt;/body&gt;
&lt;/html&gt;

Sub-template inheritance

{% extends "" %}

{% block title %}User Home Page - {{ super() }}{% endblock %}

{% block head %}
    {{ super() }}
    &lt;style&gt;
        .profile { color: blue; }
    &lt;/style&gt;
{% endblock %}

{% block content %}
    &lt;div class="profile"&gt;
        &lt;h1&gt;{{  }}Personal profile&lt;/h1&gt;
        &lt;p&gt;age: {{  }}&lt;/p&gt;
    &lt;/div&gt;
{% endblock %}

{% block footer %}
    &lt;footer&gt;
        &lt;p&gt;&amp;copy; 2023 User Center&lt;/p&gt;
    &lt;/footer&gt;
{% endblock %}

Includes other templates

&lt;!-- Includes head --&gt;
{% include '' %}

&lt;!-- With parameters included --&gt;
{% include 'user_card.html' with user=current_user %}

&lt;!-- Ignore missing templates --&gt;
{% include '' ignore missing %}

3. Load static files

Static file organization

Standard project structure:

myapp/
├──
├── static/
│   ├── css/
│   ├── js/
│   └── images/
└── templates/

Reference static files

&lt;!-- CSSdocument --&gt;
&lt;link rel="stylesheet" href="{{ url_for('static', filename='css/') }}" rel="external nofollow" &gt;

&lt;!-- JavaScriptdocument --&gt;
&lt;script src="{{ url_for('static', filename='js/') }}"&gt;&lt;/script&gt;

&lt;!-- picture --&gt;
&lt;img src="{{ url_for('static', filename='images/') }}" alt="Logo"&gt;

&lt;!-- Use cache clearance --&gt;
&lt;link rel="stylesheet" href="{{ url_for('static', filename='css/', v=1.0) }}" rel="external nofollow" &gt;

Static file version control

Add a version number to the configuration:

['SEND_FILE_MAX_AGE_DEFAULT'] = 3600  #1 hour cache['STATIC_VERSION'] = '1.0.0'

Used in templates:

<link rel="stylesheet" href="{{ url_for('static', filename='css/') }}?v={{ config.STATIC_VERSION }}" rel="external nofollow" >

Using CDN resources

{% if config.CDN_ENABLED %}
    <script src="/jquery/3.6."></script>
{% else %}
    <script src="{{ url_for('static', filename='js/') }}"></script>
{% endif %}

The above is a detailed explanation of the use of Flask templates and advanced techniques in Python. For more information about Python Flask templates, please follow my other related articles!