【Python】Jinja2:快速上手

2024-08-24 16:12
文章标签 python 快速 jinja2

本文主要是介绍【Python】Jinja2:快速上手,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Jinja2 是一个广泛使用的 Python 模板引擎,它允许你使用模板语法生成动态的 HTML、XML、或者其他文本文件。Jinja2 是 Flask 和 FastAPI 等 Web 框架中默认的模板引擎,但它也可以在任何 Python 项目中独立使用。

部署与使用

安装

pip install jinja2

导入模块和类

from jinja2 import Environment, FileSystemLoader
  • jinja2 是 Jinja2 模板引擎的 Python 模块。
  • Environment 是 Jinja2 的核心类之一,负责管理模板的全局配置、变量的全局设置,以及模板文件的加载方式。
    • Environment 的作用:这个类用于创建模板环境,管理模板的全局配置,如自动转义、缓存设置、扩展的使用等。在 Environment 对象中,可以定义如何加载模板、模板的编码格式、全局变量和过滤器等。
  • FileSystemLoader 是 Jinja2 中的一种加载器,用于从文件系统中的指定目录加载模板文件。
    • 加载器的作用:Jinja2 提供了多种加载器,FileSystemLoader 是其中最常用的一种,适用于从文件系统加载模板。加载器的作用是告诉 Jinja2 如何找到和读取模板文件。

创建模板环境

env = Environment(loader=FileSystemLoader('templates'))
  • env:这是一个 Environment 类的实例,代表 Jinja2 模板的全局环境。
    • Environment 的实例化:通过 Environment() 创建的 env 对象,负责管理和存储所有模板相关的配置和信息。
  • loader=FileSystemLoader('templates')
    • loader 参数Environment 类的一个关键参数,用于指定模板文件的加载器。在这里,我们使用 FileSystemLoader 加载器。
    • FileSystemLoader('templates'):指定了模板文件所在的目录 'templates',表示所有的模板文件都存放在这个文件夹中。
      • 作用:当你在后续代码中请求模板时,Jinja2 会在 templates 目录中查找相应的模板文件。

代码扩展:

可以在 Environment 中传递更多的配置参数,例如:

env = Environment(loader=FileSystemLoader('templates'),autoescape=True,  # 自动转义 HTML 特殊字符,防止 XSS 攻击cache_size=50,    # 设置缓存大小,提高模板加载的效率trim_blocks=True,  # 去除块级标签中的空白行lstrip_blocks=True  # 去除块级标签前的空白字符
)

加载模板

template = env.get_template('my_template.html')
  • template:这是一个 Template 对象,表示加载的模板文件。
    • 作用template 对象持有了 my_template.html 模板的内容,可以使用这个对象进行渲染操作。
  • env.get_template('my_template.html')
    • get_template 方法:这是 Environment 类的一个方法,用于加载指定的模板文件。
    • 参数 'my_template.html':指定了要加载的模板文件的名称。
      • 路径查找:Jinja2 会在 FileSystemLoader 指定的目录(即 'templates' 文件夹)中查找名为 my_template.html 的文件,并将其作为模板进行加载。
      • 返回值get_template() 方法返回一个 Template 对象,代表该模板文件,可以使用它进行渲染。

代码扩展:

  • 处理不存在的模板文件
    • 如果模板文件不存在,get_template 会抛出 TemplateNotFound 异常。你可以通过 try...except 结构来处理这个错误。
      try:template = env.get_template('non_existent_template.html')
      except TemplateNotFound:print("Template file not found!")
      

渲染模板

rendered_html = template.render(user_name="Alice", user_is_admin=True)
  • rendered_html:这是一个字符串变量,存储了渲染后的 HTML 或其他格式的内容。

    • 作用rendered_html 是模板渲染的最终结果,即在模板中填充变量后的完整内容,通常是 HTML 代码,但也可以是任何字符串形式的内容(例如纯文本、JSON 等)。
  • template.render()

    • render 方法:这是 Template 类的一个方法,用于将模板中的占位符替换为实际的值,从而生成最终的输出。
    • 作用render 方法会解析模板中的变量和控制结构,将传递的实际值插入到模板中,生成渲染后的内容。
  • 参数传递

    • user_name="Alice":向模板传递一个名为 user_name 的变量,值为 "Alice"
      • 作用:模板中所有引用 user_name 变量的地方都会被替换为 "Alice"
    • user_is_admin=True:向模板传递一个名为 user_is_admin 的布尔变量,值为 True
      • 作用:模板中所有引用 user_is_admin 变量的地方都会被替换为 True,并且可以用于控制结构(如条件语句)来决定是否显示特定内容。

代码扩展:

假设我们有以下模板 my_template.html

<!DOCTYPE html>
<html>
<head><title>User Info</title>
</head>
<body><h1>Welcome, {{ user_name }}!</h1>{% if user_is_admin %}<p>You have admin privileges.</p>{% else %}<p>You are a regular user.</p>{% endif %}
</body>
</html>

当我们使用 template.render(user_name="Alice", user_is_admin=True) 渲染这个模板时,最终生成的 rendered_html 将是:

<!DOCTYPE html>
<html>
<head><title>User Info</title>
</head>
<body><h1>Welcome, Alice!</h1><p>You have admin privileges.</p>
</body>
</html>

使用多变量渲染

除了单一变量传递外,render 方法可以接受任意数量的键值对参数:

rendered_html = template.render(user_name="Bob",user_is_admin=False,greeting="Hello",notifications=5
)

对应的模板可能会这样写:

<h1>{{ greeting }}, {{ user_name }}!</h1>
{% if notifications > 0 %}
<p>You have {{ notifications }} new notifications.</p>
{% else %}
<p>No new notifications.</p>
{% endif %}

渲染结果会是:

<h1>Hello, Bob!</h1>
<p>You have 5 new notifications.</p>

模板

变量插值

Jinja2 允许在模板中使用双花括号 {{ }} 语法插入变量。变量插值是 Jinja2 最基本的功能之一,通常用于动态生成内容。

示例代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Welcome Page</title>
</head>
<body><h1>Hello, {{ user_name }}!</h1><p>Welcome to our website. Your email is: {{ user_email }}</p>
</body>
</html>
Python 代码:
from jinja2 import Environment, FileSystemLoader# 创建 Jinja2 环境,指定模板文件的路径
env = Environment(loader=FileSystemLoader('templates'))# 加载模板文件
template = env.get_template('welcome.html')# 定义模板中需要插入的变量
context = {'user_name': 'Alice','user_email': 'alice@example.com'
}# 渲染模板并生成最终的 HTML
rendered_html = template.render(context)
print(rendered_html)
解释:
  • 变量插值{{ user_name }} 会在最终的 HTML 中被替换为 Alice{{ user_email }} 会被替换为 alice@example.com
  • 输出:最终生成的 HTML 将是:
    <h1>Hello, Alice!</h1>
    <p>Welcome to our website. Your email is: alice@example.com</p>
    

控制结构

Jinja2 支持常见的控制结构,如条件语句 (if)、循环 (for),这使得模板能够根据条件或数据动态生成不同的内容。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>User Dashboard</title>
</head>
<body><h1>Dashboard</h1>{% if user_is_admin %}<p>Welcome, admin! You have full access to the system.</p>{% else %}<p>Welcome, user! Your access is limited.</p>{% endif %}
</body>
</html>
context = {'user_is_admin': True
}rendered_html = template.render(context)
print(rendered_html)
循环语句示例代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Product List</title>
</head>
<body><h1>Available Products</h1><ul>{% for product in products %}<li>{{ product.name }} - ${{ product.price }}</li>{% else %}<li>No products available</li>{% endfor %}</ul>
</body>
</html>
Python 代码:
context = {'products': [{'name': 'Laptop', 'price': 1200},{'name': 'Smartphone', 'price': 800},{'name': 'Tablet', 'price': 450}]
}rendered_html = template.render(context)
print(rendered_html)
解释:
  • 条件语句{% if user_is_admin %} 判断用户是否为管理员,输出相应的欢迎信息。
  • 循环{% for product in products %} 遍历 products 列表,生成每个产品的列表项。如果 products 列表为空,{% else %} 分支会显示 “No products available”。
  • 输出
    <ul><li>Laptop - $1200</li><li>Smartphone - $800</li><li>Tablet - $450</li>
    </ul>
    

过滤器

Jinja2 提供了一系列内置过滤器,用于在模板中对变量进行格式化和处理。过滤器使用管道符号 | 进行应用,类似于 Unix 的管道操作。

常见过滤器示例:
  • upper:将字符串转换为大写。
  • lower:将字符串转换为小写。
  • date:格式化日期。
  • length:获取列表或字符串的长度。
示例代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>User Profile</title>
</head>
<body><h1>User Profile</h1><p>Name: {{ user_name | upper }}</p><p>Member since: {{ join_date | date("Y-m-d") }}</p><p>You have {{ notifications | length }} new notifications.</p>
</body>
</html>
Python 代码:
from datetime import datetimecontext = {'user_name': 'Alice','join_date': datetime(2021, 3, 15),'notifications': ['Message 1', 'Message 2', 'Message 3']
}rendered_html = template.render(context)
print(rendered_html)
解释:
  • upper 过滤器:将 user_name 转换为大写,即 Alice 变为 ALICE
  • date 过滤器:将 join_date 格式化为 YYYY-MM-DD 格式,如 2021-03-15
  • length 过滤器:计算 notifications 列表的长度,即显示 “You have 3 new notifications”。

模板继承

模板继承是 Jinja2 的一大特色,它允许你定义一个基础模板,并在其他模板中继承和扩展该基础模板。这有助于保持代码的可维护性和一致性,尤其是在处理大型项目时。

基础模板示例代码 (base.html):
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{% block title %}My Website{% endblock %}</title>
</head>
<body><header><h1>My Website</h1><nav><a href="/">Home</a><a href="/about">About</a><a href="/contact">Contact</a></nav></header><main>{% block content %}{% endblock %}</main><footer><p>&copy; 2024 My Website</p></footer>
</body>
</html>
子模板示例代码 (home.html):
{% extends "base.html" %}{% block title %}Home - My Website{% endblock %}{% block content %}<h2>Welcome to the Home Page</h2><p>This is the main content of the home page.</p>
{% endblock %}
Python 代码:
template = env.get_template('home.html')
rendered_html = template.render()
print(rendered_html)
解释:
  • {% extends "base.html" %}home.html 继承了 base.html 中定义的结构和样式。
  • {% block title %}{% block content %}:子模板通过 block 标签重写了 base.html 中的特定部分,如标题和主要内容。
  • 输出
    <title>Home - My Website</title>
    <h2>Welcome to the Home Page</h2>
    <p>This is the main content of the home page.</p>
    

宏(Macros)

宏类似于 Python 中的函数,用于封装可重用的模板代码。使用宏可以避免重复代码,并简化复杂的模板逻辑。

宏定义与使用示例代码:
{% macro render_input(name, value='', type='text', placeholder='') %}<input type="{{ type }}" name="{{ name }}" value="{{ value }}" placeholder="{{ placeholder }}">
{% endmacro %}<form>{{ render_input('username', type='text', placeholder='Enter your username') }}{{ render_input('password', type='password', placeholder='Enter your password') }}<button type="submit">Login</button>
</form>
Python 代码:
template = env.get_template('form.html')
rendered_html = template.render()
print(rendered_html)
解释:
  • {% macro render_input %}:定义了一个名为 render_input 的宏,用于生成 <input> 表单元素。这个宏接收多个参数,如 namevaluetypeplaceholder
  • 宏的使用:通过调用 {{ render_input(...) }},可以生成自定义的输入框,而不需要重复编写 HTML 代码。
  • 输出
    <input type="text" name="username" value="" placeholder="Enter your username"><input type="password" name="password" value="" placeholder="Enter your password"><button type="submit">Login</button>

*FastAPI动态页面

在 FastAPI 中使用 Jinja2 渲染和返回动态页面是一种常见的做法,尤其是在需要生成动态 HTML 内容时。以下是详细步骤和代码示例,展示如何在 FastAPI 中集成 Jinja2 并返回动态页面。

安装依赖

首先,确保安装了 FastAPI 和 Jinja2 相关的依赖包:

pip install fastapi jinja2 uvicorn

项目结构

假设你的项目结构如下:

.
├── app.py
├── templates
│   └── index.html
  • app.py: 主应用程序文件。
  • templates: 存放 Jinja2 模板文件的目录。
  • index.html: 一个示例模板文件。

创建 FastAPI 应用并配置 Jinja2

app.py 中设置 FastAPI 应用程序并配置 Jinja2 进行模板渲染:

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponseapp = FastAPI()# 配置 Jinja2 模板引擎
templates = Jinja2Templates(directory="templates")@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):# 渲染 index.html 模板,并传递上下文变量return templates.TemplateResponse("index.html", {"request": request, "user_name": "Alice", "user_is_admin": True})
  • Jinja2Templates(directory="templates"): 这行代码配置了 Jinja2 模板引擎,指定模板文件存放在 templates 目录下。
  • @app.get("/", response_class=HTMLResponse): 这个装饰器用于定义一个 GET 路由,当用户访问 / 时,这个函数会被调用。
  • TemplateResponse("index.html", {"request": request, "user_name": "Alice", "user_is_admin": True}):
    • TemplateResponse: 渲染 Jinja2 模板并返回一个 HTML 响应。
    • "index.html": 指定要渲染的模板文件。
    • {"request": request, "user_name": "Alice", "user_is_admin": True}: 传递给模板的上下文数据,request 对象是必须的,它用于模板内部访问 URL 路径等信息,其他变量如 user_nameuser_is_admin 可以在模板中使用。

创建模板文件

templates 目录下创建 index.html 文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Welcome</title>
</head>
<body><h1>Welcome, {{ user_name }}!</h1>{% if user_is_admin %}<p>You have admin privileges.</p>{% else %}<p>You are a regular user.</p>{% endif %}
</body>
</html>
  • {{ user_name }}: 用于插入 user_name 变量的值。
  • {% if user_is_admin %}: 控制结构,用于根据 user_is_admin 的值显示不同的内容。

启动 FastAPI 应用

在终端中启动 Uvicorn 服务器以运行 FastAPI 应用:

uvicorn app:app --reload

然后访问 http://127.0.0.1:8000/,你将看到渲染后的 HTML 页面。

这篇关于【Python】Jinja2:快速上手的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102964

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

python中的flask_sqlalchemy的使用及示例详解

《python中的flask_sqlalchemy的使用及示例详解》文章主要介绍了在使用SQLAlchemy创建模型实例时,通过元类动态创建实例的方式,并说明了如何在实例化时执行__init__方法,... 目录@orm.reconstructorSQLAlchemy的回滚关联其他模型数据库基本操作将数据添

Python实现快速扫描目标主机的开放端口和服务

《Python实现快速扫描目标主机的开放端口和服务》这篇文章主要为大家详细介绍了如何使用Python编写一个功能强大的端口扫描器脚本,实现快速扫描目标主机的开放端口和服务,感兴趣的小伙伴可以了解下... 目录功能介绍场景应用1. 网络安全审计2. 系统管理维护3. 网络故障排查4. 合规性检查报错处理1.

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Python轻松实现Word到Markdown的转换

《Python轻松实现Word到Markdown的转换》在文档管理、内容发布等场景中,将Word转换为Markdown格式是常见需求,本文将介绍如何使用FreeSpire.DocforPython实现... 目录一、工具简介二、核心转换实现1. 基础单文件转换2. 批量转换Word文件三、工具特性分析优点局

Python中4大日志记录库比较的终极PK

《Python中4大日志记录库比较的终极PK》日志记录框架是一种工具,可帮助您标准化应用程序中的日志记录过程,:本文主要介绍Python中4大日志记录库比较的相关资料,文中通过代码介绍的非常详细,... 目录一、logging库1、优点2、缺点二、LogAid库三、Loguru库四、Structlogphp

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

Python海象运算符:=的具体实现

《Python海象运算符:=的具体实现》海象运算符又称​​赋值表达式,Python3.8后可用,其核心设计是在表达式内部完成变量赋值并返回该值,从而简化代码逻辑,下面就来详细的介绍一下如何使用,感兴趣... 目录简介​​条件判断优化循环控制简化​推导式高效计算​正则匹配与数据提取​性能对比简介海象运算符

python项目环境切换的几种实现方式

《python项目环境切换的几种实现方式》本文主要介绍了python项目环境切换的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 如何在不同python项目中,安装不同的依赖2. 如何切换到不同项目的工作空间3.创建项目

python项目打包成docker容器镜像的两种方法实现

《python项目打包成docker容器镜像的两种方法实现》本文介绍两种将Python项目打包为Docker镜像的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录简单版:(一次成功,后续下载对应的软件依赖)第一步:肯定是构建dockerfile,如下:第二步