WEB开发 - Flask 入门:Jinja2 模板语法进阶 Python

在上一阶段,我们一起学习了基于Python地 web框架Flask,并且初步了解了这个框架有一种渲染方式叫做 模板语法,今天,我们一起再来深入地了解和学习这个叫做Jinja2地模板语法。

WEB开发 - Flask 入门:由浅入深地带你学习

Flask 的模板渲染由Jinja2提供支持,Jinja2 是一个强大的 Python 模板引擎。现在假设你已经对它有了基本的了解,所以接下来让我们更深入地了解 Flask 模板渲染的高级功能和最佳实践。

1. Jinja2 模板语法回顾

在进一步介绍之前,这里先简单概述一下 Jinja2 的语法:

  • 变量{{ variable }}
  • 控制结构{% if condition %} ... {% endif %}{% for item in items %} ... {% endfor %}
  • 筛选器{{ variable|filter_name }}
  • 评论{# This is a comment #}
  • 继承{% extends "base.html" %}{% block content %} ... {% endblock %}

根据上面的模板语法,我们使用一个例程来实现Jinja2 模板语法回顾:

代码示例:

1.1 变量

在模板中,我们可以通过 {{ variable }} 来渲染变量的值。

示例:
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Jinja2 模板语法回顾</title>
</head>
<body>
    <h1>欢迎,{{ name }}!</h1>
    <p>你当前的年龄是:{{ age }}岁。</p>
</body>
</html>

1.2 控制结构

使用 {% %} 来执行控制结构,例如条件判断和循环。

条件判断:
{% if age >= 18 %}
    <p>你是成年人。</p>
{% else %}
    <p>你是未成年人。</p>
{% endif %}
循环:
<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

1.3. 过滤器

过滤器用于修改输出的值,比如格式化日期、文本转换等。使用 | 来调用过滤器。

示例:
<p>{{ "2024-12-27"|date("yyyy年MM月dd日") }}</p>
<p>{{ "Hello World"|lower }}</p>

1.4. 模板继承

可以通过 {% extends %}{% block %} 实现模板的继承和重用。

基本模板(base.html):
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}我的网站{% endblock %}</title>
</head>
<body>
    <header>
        <h1>{% block header %}欢迎来到我的网站{% endblock %}</h1>
    </header>

    <div class="content">
        {% block content %}内容区域{% endblock %}
    </div>

    <footer>
        {% block footer %}版权信息{% endblock %}
    </footer>
</body>
</html>

上面的基本模版在浏览器中的显示:

 

子模板(home.html):
{% extends "base.html" %}

{% block title %}首页 - 我的网站{% endblock %}

{% block content %}
    <h2>欢迎来到首页!</h2>
    <p>这里是一些重要的内容。</p>
{% endblock %}

上面的子模版在继承了基本模板之后,在浏览器中的显示(内容区域已经被子模版的内容替换掉了):

 

1.5. 自定义过滤器

你可以定义自定义的过滤器来对模板中的变量进行处理。

Python 代码(app.py):
from flask import Flask
from flask import render_template

app = Flask(__name__)

# 自定义过滤器函数
def reverse_string(value):
    return value[::-1]

# 注册自定义过滤器
app.jinja_env.filters['reverse'] = reverse_string

@app.route('/')
def home():
    return render_template('home.html')

if __name__ == '__main__':
    app.run(debug=True)
模板代码(home.html):
<p>{{ "hello"|reverse }}</p>  <!-- 输出:olleh -->

上面的webServer 运行后,在浏览器总访问效果如下:

 

你会发现,输入内容“hello” 被我们自己定义的反相器reverse给倒序了。这个反相器就是一个过滤器,你可以定义很多不同的过滤器,比如字符串截取、大小写变换、日期格式转换、字符串替换等等。

 

1.6. 模板宏

宏类似于模板中的函数,可以用来复用代码块。

示例:(macros.html)
{% macro render_item(item) %}
    <div class="item">
        <h3>{{ item.name }}</h3>
        <p>{{ item.description }}</p>
    </div>
{% endmacro %}
使用宏:(home.html)
{% from "macros.html" import render_item %}

<div class="items">
    {% for item in items %}
        {{ render_item(item) }}
    {% endfor %}
</div>

 app.js 如下

from flask import Flask, render_template

# 创建一个 Flask 实例
app = Flask(__name__)

@app.route('/home')
def greet():
    # 定义要传递给模板的数据
    items = [
        {"name": "Alice", "description": "description Alice"},
        {"name": "Tom", "description": "description Tom"}
    ]
    # 将数据传递给模板
    return render_template('home.html', items=items)

# 运行应用
if __name__ == '__main__':
    app.run(debug=True)

上述代码执行后,从浏览器访问:

 

你会发现,模板宏被调用了,显示了名字和介绍。这个模板宏,可以被很多具有相同数据结构的页面调用。它形成了一个类似vue的 component 组件。 

 

1.7. 模板包含

{% include %} 用于包含其他模板的内容,通常用于包含页面的共同部分。

示例:
<div class="sidebar">
    {% include "sidebar.html" %}
</div>

通过这些语法,Jinja2 提供了灵活而强大的模板引擎,能帮助我们高效地渲染动态内容,并且让页面结构更清晰、可维护。

2.模板继承(高级)

模板继承是 Jinja2 最强大的功能之一。它允许您定义一个基本模板并在子模板中扩展它,从而实现通用布局和结构的重用。

基本模板示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
    <header>
        <h1>{% block header %}Welcome to My Website{% endblock %}</h1>
    </header>

    <div class="content">
        {% block content %}Content goes here{% endblock %}
    </div>

    <footer>
        {% block footer %}Footer content{% endblock %}
    </footer>
</body>
</html>
子模板示例:
{% extends "base.html" %}

{% block title %}Home - My Website{% endblock %}

{% block content %}
    <h2>Welcome to the home page!</h2>
    <p>Here is some important content.</p>
{% endblock %}

这个案例和我们之前回顾的模板调用实际上一样的,在此不做赘述了,需要加深理解的可以重做一遍。 

3.动态模板渲染

您可以将数据动态传递给模板。将数据操作逻辑与 Flask 视图中的渲染逻辑分开是一种很好的做法。

Flask 路线示例:
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    data = {
        'name': 'John Doe',
        'age': 30,
        'items': ['apple', 'banana', 'cherry']
    }
    return render_template('home.html', data=data)
模板示例(home.html):
<h1>Hello, {{ data.name }}</h1>
<p>You are {{ data.age }} years old.</p>
<ul>
    {% for item in data.items %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

4.模板上下文处理器

上下文处理器是在渲染模板之前运行的函数,允许您自动将公共变量传递给所有模板。

例子:
@app.context_processor
def inject_user():
    return {'user': 'John Doe'}

这将注入user到每个模板中,因此您可以{{ user }}在任何模板中使用它而无需明确传递它。这个有点类似Node.js 的中间件,在app.j中定义好之后,继续往下路由,可以全局使用。

 

5.使用自定义错误页面处理错误

Flask 提供了一种定义自定义错误页面的方法(例如 404 或 500 错误)。你可以为这些错误渲染自定义模板。

例子:
  • 包括:用于{% include 'filename.html' %}重用模板片段。
  • 动态渲染render_template_string:有时,您可能需要从字符串而不是文件渲染模板。
  • 异步渲染:对于需要异步处理的繁重操作,您可以使用 Flask 对后台作业或流式传输数据到客户端的支持。

6.高级模板技术

  • 包括:用于{% include 'filename.html' %}重用模板片段。
  • 动态渲染render_template_string:有时,您可能需要从字符串而不是文件渲染模板。
  • 异步渲染:对于需要异步处理的繁重操作,您可以使用 Flask 对后台作业或流式传输数据到客户端的支持。

7.测试模板

Flask 有一个内置测试客户端,你可以用它来测试你的路由和模板。使用flask.testing.TestCase,你可以断言模板的渲染是否正确。

from flask import Flask, render_template
import unittest

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('home.html', name="Test")

class TemplateTest(unittest.TestCase):
    def setUp(self):
        app.config['TESTING'] = True
        self.client = app.test_client()

    def test_home_page(self):
        response = self.client.get('/')
        self.assertIn(b'Hello, Test', response.data)

if __name__ == '__main__':
    unittest.main()

 

8.Flask扩展

Flask 有许多可以简化模板的扩展,例如:

  • Flask-WTF:用于将表单集成到模板中。
  • Flask-Login:用于管理模板中的用户会话。

除了上面这些,其他还有 循环、嵌套等方法,都很容易实现,这里就不一一赘述了。

通过学习这些高级特性,你可以更灵活地使用 Flask 的模板系统,编写更加干净、可维护和扩展的模板。你可以尝试将这些功能组合在一起,用于实现更复杂的页面和功能。如果有任何问题或不清楚的地方,欢迎随时留言一起来讨论! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/943662.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot在线音乐系统平台功能实现十八

一、前言介绍&#xff1a; 1.1 项目摘要 随着互联网技术的迅猛发展和普及&#xff0c;人们对音乐的获取和欣赏方式发生了巨大改变。传统的音乐播放方式&#xff0c;如CD、磁带或本地下载的音乐文件&#xff0c;已经不能满足用户日益增长的需求。用户更希望通过网络直接获取各…

【YOLOv3】源码(train.py)

概述 主要模块分析 参数解析与初始化 功能&#xff1a;解析命令行参数&#xff0c;设置训练配置项目经理制定详细的施工计划和资源分配日志记录与监控 功能&#xff1a;初始化日志记录器&#xff0c;配置监控系统项目经理使用监控和记录工具&#xff0c;实时跟踪施工进度和质量…

[原创](Modern C++)现代C++的第三方库的导入方式: 例如Visual Studio 2022导入GSL 4.1.0

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共23年] 职业生涯: 21年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi、XCode、Eclipse…

单片机与MQTT协议

MQTT 协议简述 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布 / 订阅&#xff08;publish/subscribe&#xff09;模式的 “轻量级” 通讯协议&#xff0c;该协议构建于 TCP/IP 协议上&#xf…

力扣矩阵-算法模版总结

lc-73.矩阵置零-(时隔14天)-12.27 思路&#xff1a;(23min22s) 1.直接遍历遇0将行列设0肯定不行&#xff0c;会影响后续判断&#xff0c;题目又要求原地算法&#xff0c;那么进一步考虑是否可以将元素为0&#xff0c;其行列需要设为0的位置给存储下来&#xff0c;最后再遍历根据…

C++的第一个程序

前言 在学习c之前&#xff0c;你一定还记得c语言的第一个程序 当时刚刚开始进行语言学习 因此告诉到&#xff0c;仅仅需要记住就可以 #include <stdio.h>int main(){printf("Hello World");return 0; }而对于c中的第一个程序&#xff0c;似乎有所变化 C的…

使用jvisualvm远程连接Linux服务器上java进程

使用jvisualvm连接远程服务器有两种方式&#xff1a;JMX和jstatd&#xff0c;两种方式都不能完美支持所有功能&#xff0c;例如JMX不支持VisualGC&#xff0c;jstatd不支持CPU监控&#xff0c;实际使用可同时配置上并按需选用。 一、jstatd连接 1、在Linux中配置远程授权 要监…

麒麟操作系统服务架构保姆级教程(六)部署PHP环境

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 本来小屁打算直接写LNMP架构的&#xff08;LB负载均衡NginxmysqlPHP&#xff09;&#xff0c;但是发现之前用过的包是红帽的吗&#xff0c;在麒麟上没法直接部署PHP&#xff0c;所以小屁用两天的时间…

SpringCloudAlibaba升级手册-nacos问题记录

目录 一、前言 二、升级过程 1.问题 2.原因 3.出处 4.理论解决 5.测试环境问题 6.Spring Cloud Alibaba版本对比 7. Spring Cloud Alibaba适配组件版本对比 8.降低Spring Cloud版本 9.SpringCloud与SpringBoot兼容对比表 10.naocs-client版本对比 三、最终解决 一…

[SAP ABAP] 程序备份

备份当前程序到本地的方式如下&#xff1a; 1.复制粘贴 Ctrl A 、Ctrl V 2.【实用程序】|【更多实用程序】|【上载/下载】|【下载】 ​ 3.快捷键&#xff0c;支持多种格式导出(.abap .html .pdf 等) 在事务码SE38(ABAP编辑器)屏幕右下角&#xff0c;点击【Options选项】图…

距离25年PMP第一次考试还有70多天,如何短期通过考试?

距离205年3月考试时间具体还有78天&#xff0c;除去过年放假的时间还有2个月多一点吧&#xff0c;可以说复习时间并不是很充裕&#xff0c;那么在2个月甚至不足两个月的时间里我们该如何应对呢&#xff1f;如何短期内上岸&#xff1f; 接下来给大家分享一下我的复习方法&#…

【AIGC-ChatGPT副业提示词指令 - 动图】魔法咖啡馆:一个融合创意与治愈的互动体验设计

引言 在当今快节奏的生活中&#xff0c;咖啡早已不仅仅是提神醒脑的饮品&#xff0c;更成为了一种情感寄托和生活态度的表达。本文将介绍一个独特的"魔法咖啡馆"互动体验设计&#xff0c;通过将咖啡与情感、魔法元素相结合&#xff0c;创造出一个充满想象力和治愈感…

通过远程控制软件实现企业高效协作

在这个信息技术迅猛发展的时代&#xff0c;远程办公已经成为一种趋势&#xff0c;而远程控制软件则是连接分散团队的重要工具。技术的革新不仅推动了远程控制软件的广泛应用&#xff0c;也为现代办公带来了高效的协作体验。本文将探讨远程控制软件的发展&#xff0c;并以RayLin…

解决 vue3 中 echarts图表在el-dialog中显示问题

原因&#xff1a; 第一次点开不显示图表&#xff0c;第二次点开虽然显示图表&#xff0c;但是图表挤在一起&#xff0c;页面检查发现宽高只有100px,但是明明已经设置样式宽高100% 这可能是由于 el-dialog 还没有完全渲染完成&#xff0c;而你的 echarts 组件已经开始尝试渲染图…

MySQL如何只取根据某列连续重复行的第一条记录

前言 MySQL如何只取根据某列连续重复行的第一条记录&#xff0c;条件&#xff1a;某列、连续、验重 建表准备 DROP TABLE IF EXISTS test; CREATE TABLE test (id bigint NOT NULL,time datetime NULL DEFAULT NULL,price int NULL DEFAULT NULL,PRIMARY KEY (id) USING BT…

图文教程:使用PowerDesigner导出数据库表结构为Word/Html文档

1、第一种情况-无数据库表&#xff0c;但有数据模型 1.1 使用PowerDesigner已完成数据建模 您已经使用PowerDesigner完成数据库建模&#xff0c;如下图&#xff1a; 1.2 Report配置和导出 1、点击&#xff1a;Report->Reports&#xff0c;如下图&#xff1a; 2、点击&…

AI三驾马车——数据、算法与算力的一体化融合体验

一、概述 随着AI大模型、云计算和大数据技术的快速发展&#xff0c;智能算力市场需求持续增长。今年7月由国家信息中心发布的《智能算力产业发展白皮书》指出&#xff0c;随着AI大模型等关键技术取得突破&#xff0c;算力需求正从通用计算转向智能计算。智能计算是指面向人工智…

Vue 3 与 Tauri 集成开发跨端APP

1、安装RUST 下载地址&#xff1a;Install Rust - Rust Programming Language 安装&#xff1a; 安装完成后&#xff0c;在命令行里运行: rustup 2、安装 Node.js 与 npm 或 pnpm &#xff0c;如果已经安装&#xff0c;可以忽略 # 使用 nvm 安装 Node.js 最新版本 nvm install…

指针详解之 多层嵌套的关系

1 例子之指向3个字符串的指针数组&#xff0c;易混淆&#xff01; 1.1过程详解&#xff1a; char *str[3]{ "Hello,thisisasample!", "Hi,goodmorning.", "Helloworld" }; char s[80]&#xff1b; strcpy(s,str[0]); //也可写成strcpy(s,*st…

Keras2.0 ImageDataGenerator 适配

最近在学习keras,总遇到使用 ImageDataGenerator当作训练参数&#xff0c;使用 fit_generator(), 而 Keras 2.0 已经放弃了&#xff0c;导致执行不下去了 经过N多天的摸索&#xff0c;终于是成功了 # 训练集数据生成 datagen ImageDataGenerator(rotation_range40,rescale…