Python flask jinjia2配置使用

Python flask jinjia2配置使用

1. Flask 与 Jinja2 简介

  • Flask 是一个轻量级的 Python Web 框架,默认集成了模板引擎 Jinja2
  • Jinja2 用于将数据渲染到 HTML 页面,实现前后端分离。

2. 环境安装

参考前文 flask 开发环境搭建 

Flask 会自动安装 Jinja2。


3. 基本目录结构

推荐结构如下:

your_project/ ├── app.py ├── templates/ │ └── index.html └── static/ └── style.css 
  • templates/ 存放 Jinja2 模板
  • static/ 存放静态文件(如 CSS、JS、图片)

4. Flask 配置模板目录

Flask 默认读取 templates/ 目录。如果你想自定义:

app = Flask(__name__, template_folder='your_templates_folder') 


5. 使用 Jinja2 模板

5.1. 创建模板文件

templates/index.html:

<!DOCTYPE html> <html> <head> <title>{{ title }}</title> </head> <body> <h1>Hello, {{ name }}!</h1> <ul> {% for item in items %} <li>{{ item }}</li> {% endfor %} </ul> </body> </html> 

5.2. 后端渲染模板

app.py:

from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template( 'index.html', title='首页', name='小明', items=['苹果', '香蕉', '橘子'] ) if __name__ == '__main__': app.run(debug=True) 

6. Jinja2 语法详解

  • 变量{{ variable }}
  • 控制结构{% if %} ... {% endif %}{% for %} ... {% endfor %}
  • 注释{# 注释内容 #}
  • 过滤器{{ name|upper }}{{ list|length }}

例子

{% if items %} <ul> {% for item in items %} <li>{{ item|capitalize }}</li> {% endfor %} </ul> {% else %} <p>没有内容。</p> {% endif %} 

7. 传递更多数据类型

你可以传递字典、列表、对象等:

user = {'name': '小红', 'age': 18} return render_template('index.html', user=user) 

模板:

<p>姓名:{{ user.name }}</p> <p>年龄:{{ user.age }}</p> 


8. 模板继承

8.1. 基础模板

templates/base.html:

<!DOCTYPE html> <html> <head> <title>{% block title %}我的网站{% endblock %}</title> </head> <body> <div> {% block content %}{% endblock %} </div> </body> </html> 

8.2. 子模板

templates/index.html:

{% extends "base.html" %} {% block title %}首页{% endblock %} {% block content %} <h1>欢迎来到首页</h1> {% endblock %} 

9. 静态文件引用

模板中引用静态文件:

<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> 

10. 配置 Jinja2 高级选项

你可以自定义 Jinja2 的配置,例如自定义分隔符:

app.jinja_env.variable_start_string = '[[' app.jinja_env.variable_end_string = ']]' 

模板中就用 [[ variable ]]


11. 常见问题

  • 模板文件放错目录,导致找不到
  • 变量名拼写错误
  • 控制结构语法错误

12. Jinja2 过滤器和自定义过滤器

12.1 常用内置过滤器

  • {{ name|capitalize }} 首字母大写
  • {{ text|safe }} 标记为安全 HTML,不会被转义
  • {{ items|length }} 获取列表长度
  • {{ price|round(2) }} 保留两位小数

12.2 自定义过滤器

你可以在 Flask 中注册自己的过滤器:

def reverse_string(s): return s[::-1] app.jinja_env.filters['reverse'] = reverse_string 

模板中使用:

<p>{{ name|reverse }}</p> 

13. Jinja2 宏(Macro)

宏类似于模板中的函数,可以复用模板片段。

templates/macros.html:

{% macro render_input(name,, type='text') %} <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> {% endmacro %} 

引用宏

{% import "macros.html" as macros %} {{ macros.render_input('username') }} 

14. Jinja2 包含(Include)

可以将公共片段抽取出来:

templates/header.html:

<header> <h1>网站头部</h1> </header> 

在主模板中使用

{% include 'header.html' %} 

15. Jinja2 循环控制

  • loop.index 当前循环索引(从1开始)
  • loop.index0 当前循环索引(从0开始)
  • loop.first 是否第一个元素
  • loop.last 是否最后一个元素
<ul> {% for item in items %} <li>{{ loop.index }}: {{ item }}</li> {% endfor %} </ul> 

16. 模板全局变量和上下文处理器

你可以为所有模板注入全局变量:

@app.context_processor def inject_user(): return dict(site_name='我的网站') 

模板中直接使用:

<p>{{ site_name }}</p> 

17. 模板错误处理

如果模板变量不存在,默认不会报错而是显示空白。你可以用 default 过滤器:

{{ user.name|default('匿名') }} 


18. Jinja2 与 Flask 表单结合(简单例子)

app.py:

from flask import Flask, render_template, request app = Flask(__name__) @app.route('/form', methods=['GET', 'POST']) def form(): if request.method == 'POST': username = request.form.get('username') msg = f'你好,{username}!' return render_template('form.html', msg=msg) if __name__ == '__main__': app.run(debug=True) 

templates/form.html:

<form method="post"> <input type="text" name="username"> <input type="submit" value="提交"> </form> <p>{{ msg }}</p> 

19. 模板缓存与自动刷新

开发阶段建议开启 debug=True,模板修改会自动刷新。生产环境建议关闭自动刷新以提升性能。


20. Jinja2 安全:自动转义与 safe 过滤器

Jinja2 默认会自动转义变量,防止 XSS 攻击。如果你确定内容安全,可以使用 safe

{{ html_content|safe }} 

21. 多模板目录配置

如果你的项目有多个模板目录,可以这样配置:

from flask import Flask from jinja2 import ChoiceLoader, FileSystemLoader app = Flask(__name__) app.jinja_loader = ChoiceLoader([ FileSystemLoader('templates'), FileSystemLoader('more_templates') ]) 

22. 国际化(i18n)支持

Flask-Babel 可以帮助你实现模板的多语言支持:

pip install flask-babel 

配置和模板用法请参考 Flask-Babel 文档


23. Jinja2 调试技巧

  • 使用 {% set var = value %} 在模板中定义变量
  • 使用 {% debug %} 可以打印当前上下文(需要手动扩展)

24. 复杂项目推荐结构

your_project/ ├── app.py ├── templates/ │ ├── base.html │ ├── index.html │ └── macros.html ├── static/ │ ├── css/ │ └── js/ ├── blueprints/ │ └── user.py └── config.py 

25. Jinja2 条件判断的高级用法

Jinja2 支持复杂的条件表达式:

{% if score >= 90 %} <p>优秀</p> {% elif score >= 60 %} <p>及格</p> {% else %} <p>不及格</p> {% endif %} 

还可以进行逻辑运算:

{% if user and user.is_admin %} <p>管理员操作区</p> {% endif %} 

26. Jinja2 设置变量和作用域

在模板内部可以设置变量:

{% set total = price * quantity %} <p>总价:{{ total }}</p> 

变量作用域仅限于当前块或模板,不会影响到其他地方。


27. Jinja2 的“块”与模板继承的实战

基础模板 base.html

<!DOCTYPE html> <html> <head> <title>{% block title %}默认标题{% endblock %}</title> </head> <body> <nav> {% block nav %}默认导航{% endblock %} </nav> <main> {% block content %}{% endblock %} </main> </body> </html> 

子模板 page.html

{% extends "base.html" %} {% block title %}具体页面标题{% endblock %} {% block nav %} <a href="/">首页</a> | <a href="/user">用户中心</a> {% endblock %} {% block content %} <h1>页面内容</h1> {% endblock %} 

这样可以实现高度复用和灵活扩展。


28. Jinja2 的“super”用法

如果你想在子模板里保留父模板的内容,可以用 {{ super() }}

{% block nav %} {{ super() }} <a href="/help">帮助</a> {% endblock %} 

29. Jinja2 的 include 与 with 语法

可以传递变量给被 include 的模板:

{% include "user_card.html" with context %} 

或者只传递部分变量:

{% include "user_card.html" with user=user, show_detail=True %} 


30. Jinja2 的循环嵌套与 break/continue

Jinja2 支持嵌套循环,但不支持 break/continue,可以通过条件控制:

{% for user in users %} {% if user.is_active %} <p>{{ user.name }}</p> {% endif %} {% endfor %} 

31. Jinja2 的 set 用法与复杂表达式

可以用 set 定义列表或字典:

{% set colors = ['red', 'green', 'blue'] %} {% for color in colors %} <span>{{ color }}</span> {% endfor %} 

32. Flask 模板自动加载和缓存控制

  • debug=True 时,模板修改会自动刷新。
  • 生产环境建议关闭 debug,模板会缓存,提升性能。

33. Flask 使用 Blueprint 时的模板组织

假设你有如下结构:

your_project/ ├── app.py ├── user/ │ ├── __init__.py │ └── templates/ │ └── user/ │ └── profile.html 

在蓝图里渲染模板:

from flask import Blueprint, render_template user_bp = Blueprint('user', __name__, template_folder='templates') @user_bp.route('/profile') def profile(): return render_template('user/profile.html') 

34. 模板中的静态文件版本控制(缓存 bust)

可以用 url_for 加版本参数:

<link rel="stylesheet" href="{{ url_for('static', filename='style.css', v='20250801') }}"> 


35. Jinja2 的自定义全局函数

可以注册全局函数:

def greet(name): return f'你好,{name}!' app.jinja_env.globals['greet'] = greet 

模板中使用:

<p>{{ greet('小明') }}</p> 

36. Jinja2 的模板继承与 include 的区别

  • 继承:用于页面整体结构、布局复用(如 base.html)。
  • include:用于局部片段复用(如导航条、用户卡片)。

37. Jinja2 的“自定义标签”扩展(高级)

如果你需要自定义标签,可以编写 Jinja2 Extension(需要较高水平,一般用不到)。


38. 常见错误与排查方法

  • 模板找不到:检查路径和文件名,建议用绝对路径或 Blueprint 的 template_folder
  • 变量未定义:检查后端传参是否一致。
  • 循环或判断语法错误:注意 {% %} 和 {{ }} 的区别。
  • 静态文件无法加载:检查 static 文件夹和 url_for 用法。
  • 中文乱码:确保模板文件保存为 UTF-8 编码。

39. 实战案例:博客文章列表

app.py:

@app.route('/blog') def blog(): posts = [ {'title': '第一篇', 'author': '小明', 'content': '内容1'}, {'title': '第二篇', 'author': '小红', 'content': '内容2'}, ] return render_template('blog.html', posts=posts) 

templates/blog.html:

<h2>博客列表</h2> <ul> {% for post in posts %} <li> <h3>{{ post.title }}</h3> <p>作者:{{ post.author }}</p> <div>{{ post.content }}</div> </li> {% endfor %} </ul>