Flask 之 Jinjia2 模板引擎必知必会

本文详细介绍了如何在Flask应用中使用Jinja2模板引擎,包括模板的创建、变量注入、链接生成、控制结构、模板包含与继承、宏指令、全局对象注册以及变量过滤器的使用。
Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

模板的作用是内容注入、页面继承与包含,Jinja2 模板引擎为此实现了一整套完善的解决方案。

在使用模板时,所有静态资源应放置在 static 资源目录下,模板页面应放置在 templates 模板目录下。


1.使用模板

首先,在 templates 模板目录下创建一个模板页面文件 value.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注入变量</title>
</head>
<body>
    测试内容
</body>
</html>

在视图函数中,调用模板渲染函数便可生成图片。

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/value')
def value(username=None):
    return render_template('value.html')


if __name__ == "__main__":
    app.run()

2.基本语法

以下是 3 种基本语法,在接下来的代码中将会经常出现。

  • {% ... %} 为控制语句,常用于实现结构控制,定义模板、变量等。
  • {{ ... }} 为表达式语句,常用于输出变量,调用宏观指令、对象函数等。
  • {# ... #} 为注释语句,用于添加代码注解。

3.注入变量

如果只是加载模板,那么网页呈现出的效果其实与静态页面无异。要实现动态网页,需要根据不同的情况显示不同的内容,这个过程便是注入变量。

注入变量的过程通常分两步,首先,在视图函数中注入变量。

@app.route('/value')
@app.route('/value/<string:username>')
def value(username=None):
    return render_template('value.html', username=username)

其次,如果需要将变量显示到页面中,则需要在模板文件中使用表达式语句输出变量,示例代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注入变量</title>
</head>
<body>
    {# 在表达式语句中,可使用 or 为变量添加默认值 #}
    <h1>{{ username or '游客'}}</h1>
    <h2> 欢迎使用!!! </h2>
</body>
</html>

4.生成链接

在 Flask 构建的网络中,每一个功能都对应一个视图函数。如果需要将不同的页面联系起来,便需要使用链接标签。在通常情况下,链接标签中所对应的链接可以在模板中使用函数 url_for() 生成。

    <!--  生成静态文件链接  -->
    <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap.min.css)}}">
    <!--  生成路由链接  -->
    <a href="{{ url_for('value') }}">
        注入变量演示
    </a>
    <!--  生成路由链接(带参数)  -->
    <a href="{{ url_for('value', username='admin) }}">
        注入变量演示(username=admin)
    </a>

5.控制结构

下面是一个文章列表的视图函数,参数 num 用于控制文章列表(模拟)的文章数量,在生成文章列表之后,将其注入模板中进行显示。

@app.route('/control')
@app.route('/control/<int:number>')
def control(num=0):
    # 此处使用 list 模拟文章列表
    articles = []
    for i in range(1, num+1):
        articles.append({
            'title'   : '文章%d标题' % i,
            'content' : ('文章%d内容' % i) * i,
        })
    return render_template('control.html', num=num, articles=articles)

文章列表页模板(control.html)的代码如下,这里给出了 iffor 语句的基本使用方式的简单例子,我们会发现这些语句与 Python 的控制语句相似,同时又类似与 HTML 标签,需要使用 {% end*** %} 语句,对前面的控制语句进行闭合。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>控制结构</title>
</head>
<body>
    <h1>文章列表</h1>
    {% if num <=0 %}
        <h2> 文章数量为 0,没有内容可展示 </h2>
    {% else %}
    {% for article in articles %}
        <h2>{{ article.title }}</h2>
        <p>{{ article.content }}</p>
    {% endfor %}
    {% endif %}
</body>
</html>

6.模板的包含与继承

  • 模板可以用于解决公共内容的冗余问题。例如,将公共部分的内容分离到一个单独的文件,再将模板加载到需要使用的页面中。如果按这种模式进行开发,在修改公共部分内容时,仅需要修改公共部分内容所处的文件,大大缩短了修改各个页面的时间。
  • 在大多数的情况下,模板包含可以实现大部分功能,但是以模板包含的方式进行网站开发,仍然需要在每一个页面中添加包含代码。
  • 而当包含页面的代码也是公共部分时,模板包含便不再适用,此时应引入新的方式进行开发——模板继承。

基准页extends_base.html{% block %} 语句用于定义可被继承页面修改的区块

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
            {# 网页标题 #}
        {% endblock %}
    </title>
    {% block head %}
        {# 网页所引用的样式等静态资源 #}
    {% endblock %}
</head>
<body>
    {% block content %}
        {# 网页内容 #}
    {% endblock %}
    {% block script %}
        {# 网页所引用的 JavaScript 资源 #}
    {% endblock %}
</body>
</html>

前端基准页 extends_bootstrap.html
由于前端统一使用 Bootstrap 框架进行开发,所以需要建立一个前端网页的基准页,以自动引入相关静态资源及加载导航栏。

{% extends 'extends_base.html' %}
{% block head %}
    <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap.min.css') }}">
{% endblock %}
{% block script %}
    <script src="{{ url_for('static', filename='jquery.min.js') }}"></script>
    <script src="{{ url_for('static', filename='bootstrap.min.js') }}"></script>
{% endblock %}
{% block content %}
    {% include 'include_nav.html' %}
    <div class="container">
        {% block inner_content %}
            {# 模板页面的正文内容 #}
        {% endblock %}
    </div>
{% endblock %}

包含导航栏模板的完整页面 extends.html

{% extends 'extends_bootstrap.html' %}
{% block title %}模板的继承、包含{% endblock %}
{% block inner_content %}
    <h1>模板的继承</h1>
    <p>可以使复杂的机构变简单。以免在多个页面中引用静态资源。</p>
    <h1>模板的包含</h1>
    <p>可以使复杂的部分单独拆分到某一个文件。</p>
{% endblock %}
{% block script %}
    {# 继承模板内容并添加新内容 #}
    {{ super() }}
    <script>
        // 以下代码用于添加文字动画
        let items = $('h1.p');
        items.hide();
        items.fadeIn(1000);
    </script>
{% endblock %}

添加视图函数

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

7.宏指令

模板的包含、继承也只是从已经编好的模板中加载相应的内容,并将模板内容覆盖到当前页面下。在常见的应用中,会有包含相同文章项目的页面,例如网站首页中和文章列表页面中包含相同的文章项目,此时,文章项目的显示代码就需要在两个页面中重复编写,这种方式操作起来较为繁琐,消耗的资源也较多。此时的文章项目属于公共部分,但在需要多次生成文章项目的情况下,包含和继承便不再适合,宏指令便是此问题的解决方案。

宏命令并不复杂,类似于 Python 中的函数,拥有参数,可以被调用,用于生成网页内容。

视图函数

@app.route('/macro')
@app.route('/macro/<int:num>')
def macro(num=0):
    # 此处使用 list 模拟文章列表
    articles = []
    for i in range(1, num+1):
        articles.append({'title'   : '文章%d标题' % i,
                         'content' : ('文章%d内容' % i) * i,
                         })
    return render_template('macro.html',
                           num      = num,
                           num_prev = num - 1,
                           num_next = num + 1,
                           articles = articles)

模板文件 macro.html

{% extends 'extends_bootstrap.html' %}
    {# 宏指令可以定义在单独的文件中,然后被其他文件引入 #}
{% import 'macro_define.html' as macro %}
{% block title %}
    宏指令
{% endblock %}
{% block inner_content %}
{# 宏指令的使用方法类似于函数 #}
{{ macro.article_list(articles, num) }}
{% if num > 0 %}
    <a href="{{ url_for('macro', num=num_prev) }}" class="btnbtn-primary">-1</a>
{% endif %}
    <a href="{{ url_for('macro', num=num_next) }}"class="btn btn-primary">+1</a>
{% endblock %}

宏指令模板文件 macro_define.html

{% macro article_item(title, content) %}
    <h2>{{ title }}</h2><p>{{ content }}</p>
{% endmacro %}
{% macro article_list(articles, article_num) %}
{% if article_num <= 0 %}
    <h2> 文章数量为0,没有内容可展示。</h2>
{% else %}
{% for article in articles %}
    {{ article_item(article.title, article.content) }}
{% endfor %}
{% endif %}
{% endmacro %}

8.注册全局对象

在某些特殊的模板中,可以通过直接调用函数来获取数据。但在被继承的模板中,如果需要调用某个固定的函数,通常需要在每一个使用被继承模板的视图函数中注入相应的函数(变量),但这显然不是推荐的操作方法。这时,需要注册全局对象。

模板文件 global.html

{% extends 'extends_bootstrap.html' %}
{% block title %}
    注册全局对象
{% endblock %}
{% block inner_content %}
    {#  此处将数字列表输出到页面中 #}
    {{ global_test(10) }}
{% endblock %}

全局对象使用示例

# 注册全局对象的类型不限,可以是任何类型(函数亦可)
def range_list(x):
    return list(range(x))
# 将函数注册到全局对象中
app.add_template_global(range_list, 'global_test')

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

9.变量过滤器

变量过滤器用于对注入变量进行简单处理。在模板页面注入变量时,只需要在变量后面添加 | 即可调用过滤器方法。

常见的过滤器基本用法

{#  字符串的首字母大写,其他小写 #}
<p>{{ 'test' | capitalize }}</p>
{#  字符串格式化 #}
<p>{{ '你好 %s ,这里是 %s 。' | format(request.remote_addr, request.path) }}</p>
{#  字符串转小写 #}
<p>{{ 'TESTTEST' | lower }}</p>
{#  字符串转大写 #}
<p>{{ 'testtest' | upper }}</p>
{#  字符串替换 #}
<p>{{ 'Hello Test' | replace('Test', 'World') }}</p>
{#  翻转字符串 #}
<p>{{ '?uoy era woH' | reverse }}</p>
{#  清除字符串首尾多余的空格 #}
<p>{{ '    这 是 一 段 测 试 内 容    ' | trim }}</p>
{#  截断字符串 #}
<p>{{ '这 是 一 段 测 试 内 容' | truncate(8) }}</p>
{#  计算字符串中单词的数量 #}
<p>{{ 'How are you?' | wordcount }}</p>
{#  四舍五入 #}
<p>{{ 1.3 | round }}</p><p>{{ 1.5 | round }}</p>
{#  为未定义的变量提供默认值 #}
<p>{{ undefined | default('默认值') }}</p>
{#  保留HTML 实体,不对内容进行转义 #}
<p>{{ '<script>alert("这里是safe 变量过滤器演示,请不要在不安全的数据中使用,否则用户将会受到攻击;就如这个弹框(恶意代码)。")</script>' | safe }}</p>
{#  对HTML 实体字符进行转义 #}
<p>{{ '<script>alert("test")</script>' | escape }}</p>
{#  清除字符串中包含的HTML 标签 #}
<p>{{ '<script>alert("test")</script>' | striptags }}</p>
{#  将对象转换为JSON 格式,通常在<script> 标签对中使用 #}<script>let data = {{ {'name': request.remote_addr} | tojson }};alert("你好呀!" + data["name"]);</script>
{#  对内容进行URL 编码 #}
<a href="?keyword={{ '这 是 一 段 测 试 内 容' | urlencode }}"> 链接</a>

自定义过滤器

# 自定义一个转换时间的过滤器
def convert_time(t):
    return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
# 注册模板变量过滤器
app.add_template_filter(convert_time)

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

内容概要:本文围绕“单相逆变器闭环逆变电路PWM模型仿真研究”展开,基于Simulink平台构建单相逆变器的闭环控制系统仿真模型,重点研究PWM调制技术在逆变电路中的应用与实现。文中详细阐述了系统架构设计、电压电流双闭环控制策略的实现原理、控制器参数设计及仿真建模全过程,并通过仿真结果验证了控制方案在动态响应、稳态精度与系统稳定性方面的有效性。同时,文档还涵盖多种电力电子系统典型应用场景,如多类型短路故障仿真(中性点不接地、经小电阻接地、经消弧线圈接地等)、软开关技术、微电网能量管理、MPPT控制等,体现出较强的技术综合性和工程实践价值。; 适合人群:电气工程、自动化、电力电子与新能源等相关专业的高校本科生、研究生、科研人员,以及从事电力系统仿真、逆变器设计与新能源并网技术研发的工程技术人员。; 使用场景及目标:①掌握基于Simulink的单相逆变器闭环控制系统建模与PWM仿真方法;②深入理解双闭环控制、SPWM/SVPWM调制、系统稳定性分析等核心技术原理;③为课程设计、毕业设计、科研项目或实际工程开发提供可复用的仿真模型与技术支持; 阅读建议:建议结合文中仿真模型动手实践,重点掌握PI控制器参数整定、PWM信号生成机制与仿真结果分析方法,同时可延伸学习文档中涉及的软开关、故障仿真、微电网控制等关联技术,以拓展系统级设计能力。
重要提示】本资源设置为0积分下载,若非0积分请勿轻易下载 亲爱的CSDN用户: 首先感谢你点进这个资源页面。我需要提前说明一个重要情况: 本资源原本已设置为“0积分下载”,即作者希望完全免费共享。但CSDN平台有时会根据文件的下载热度、文件大小、用户权限等因素,自动将部分资源的积分调整为非0数值(如1积分、2积分、5积分等)。这是平台系统的自动行为,而非作者本人的设定。 因此,如果你当前看到该资源的下载所需积分不是0(例如显示为1、2、3……),请谨慎决定是否下载。 如果你按照非0积分支付并下载后发现资源内容不符合预期、链接失效,或者实际上该资源本应是免费的,作者无法为此承担积分损失或退还操作。强烈建议:仅在页面显示为0积分时进行下载。 另外,本资源描述中并未直接提供具体的下载地址或外部链接,因为它本身是一个通过CSDN官方上传通道提交的文件/内容包。如果你看到描述中没有外部网盘地址,这是正常的——资源文件应通过CSDN内置的“下载”按钮获取。若因平台积分显示异常导致你支付了积分,请优先联系CSDN客服咨询积分退还政策,作者没有权限修改平台自动设定的积分值。 感谢你的理解与支持。技术分享本应开放,但受限于平台规则,特此提醒如上。祝学习进步!
重要提示】本资源设置为0积分下载,若非0积分请勿轻易下载 亲爱的CSDN用户: 首先感谢你点进这个资源页面。我需要提前说明一个重要情况: 本资源原本已设置为“0积分下载”,即作者希望完全免费共享。但CSDN平台有时会根据文件的下载热度、文件大小、用户权限等因素,自动将部分资源的积分调整为非0数值(如1积分、2积分、5积分等)。这是平台系统的自动行为,而非作者本人的设定。 因此,如果你当前看到该资源的下载所需积分不是0(例如显示为1、2、3……),请谨慎决定是否下载。 如果你按照非0积分支付并下载后发现资源内容不符合预期、链接失效,或者实际上该资源本应是免费的,作者无法为此承担积分损失或退还操作。强烈建议:仅在页面显示为0积分时进行下载。 另外,本资源描述中并未直接提供具体的下载地址或外部链接,因为它本身是一个通过CSDN官方上传通道提交的文件/内容包。如果你看到描述中没有外部网盘地址,这是正常的——资源文件应通过CSDN内置的“下载”按钮获取。若因平台积分显示异常导致你支付了积分,请优先联系CSDN客服咨询积分退还政策,作者没有权限修改平台自动设定的积分值。 感谢你的理解与支持。技术分享本应开放,但受限于平台规则,特此提醒如上。祝学习进步!
内容概要:本文系统阐述了CUDA并行计算的核心优化技巧,围绕提升SM利用率、最大化内存带宽、隐藏访存延迟和减少指令开销四大目标,从GPU硬件架构、线程模型、内存访问、指令执行、内核设计及工程实践六个维度展开。重点讲解了线程块配置、Warp分支发散规避、全局内存合并访问、共享内存Bank冲突避免、寄存器与常量内存使用、异步传输与多流并行、快速数学函数、原子操作优化、内核拆分与融合、Tensor Core利用等关键技术,并提供了编译优化参数和Nsight系列性能分析工具的使用指导,形成了一套完整的CUDA性能优化方法论。; 适合人群:具备CUDA编程基础,从事高性能计算、深度学习、科学计算或GPU加速开发的工程师与研究人员,尤其适合工作2年以上的开发者提升底层优化能力。; 使用场景及目标:①解决CUDA程序中SM利用率低、内存带宽不足、访存延迟高等性能瓶颈;②掌握从基础到高阶的系统性优化策略,实现程序性能的指数级提升;③结合Nsight工具进行性能剖析与迭代优化。; 阅读建议:学习时应结合实际代码调试与性能分析工具(如Nsight Compute和Nsight Systems)进行验证,优先实施线程块配置、合并访问、-O3编译等低成本高回报的基础优化,再逐步深入共享内存优化、内核融合、Tensor Core利用等高阶技术,同时推荐优先使用cuBLAS、cuDNN等NVIDIA官方优化库以逼近硬件极限性能。
内容概要:本文提供了一份完整的“大学生创新创业训练计划项目”申报材料模板包,围绕“基于深度学习的智能垃圾分类回收箱设计与实现”项目,详细展示了从项目申报书、答辩PPT、中期检查表到结题报告的全套规范文档。内容涵盖项目背景、目标、研究内容、技术路线、创新点、进度安排、预期成果、经费预算及风险应对等关键环节,并以实际案例呈现各阶段成果,如YOLOv8轻量级模型识别准确率达96%、单台成本控制在780元、校园试点回收520kg可回收物、获得软著与论文成果等,形成可复制推广的校园绿色解决方案。; 适合人群:参与大学生创新创业训练计划(大创项目)的本科生团队,尤其是工科类、计算机相关专业、有意向开展人工智能+环保类实践项目的1-3年级学生;同时也适用于指导教师和项目评审人员作为参考模板。; 使用场景及目标:①帮助学生团队系统规划并撰写高质量的大创项目申报书与结题报告;②指导项目全过程管理,包括技术实施、进度控制、经费使用与成果凝练;③支撑项目答辩展示,提升项目规范性与竞争力,冲击“互联网+”“挑战杯”等赛事奖项; 阅读建议:此资源不仅提供文本模板,更体现了项目从立项到结题的完整逻辑链条,使用者应结合自身课题,参照其结构化表达方式、量化目标设定和技术落地路径进行模仿与创新,注重理论与实践结合,强化数据支撑与成果可视化。
内容概要:本文提供了一个基于Simulink的光伏储能单相逆变器并网仿真模型,系统实现了并网逆变电路的PWM调制控制、闭环控制策略及并网运行特性的仿真分析,涵盖系统建模、控制算法设计、稳定性验证与动态性能评估等关键环节。该模型不仅支持对单相逆变器在并网过程中的电流谐波、功率因数、电能质量及系统稳定性的深入研究,还可拓展应用于多类型电力系统仿真场景,如MPPT控制、软开关技术、微电网能量管理、短路故障分析(包括单相、两相接地及相间短路)、直流电机双闭环控制、Buck/Boost类变换器控制等,展现出广泛的科研适配性与工程实践价值。; 适合人群:面向具备电力电子、自动控制理论或电气工程背景,熟练掌握Simulink/Matlab仿真工具,从事新能源发电系统、微电网控制、逆变器拓扑与控制策略研究的硕士/博士研究生、科研人员及电力系统相关领域的工程技术人员。; 使用场景及目标:①开展光伏发电系统并网控制策略的设计与仿真验证;②学习并掌握单相逆变器PWM调制、锁相环(PLL)、电压电流双闭环控制等核心技术的建模方法;③作为课程设计、毕业设计或科研项目的仿真平台,支撑控制系统开发与优化;④结合文中提供的多种电力系统案例(如故障仿真、储能控制、微网调度),进行横向对比与综合能力提升; 阅读建议:建议读者结合文中列出的多个仿真案例进行扩展学习,重点关注控制器参数设计与系统动态响应之间的关系,动手复现模型并进行仿真调试,通过改变负载、电网条件或控制参数,深入理解并网逆变器的工作机理与控制规律,从而提升实际科研与工程应用能力。
重要提示】本资源设置为0积分下载,若非0积分请勿轻易下载 亲爱的CSDN用户: 首先感谢你点进这个资源页面。我需要提前说明一个重要情况: 本资源原本已设置为“0积分下载”,即作者希望完全免费共享。但CSDN平台有时会根据文件的下载热度、文件大小、用户权限等因素,自动将部分资源的积分调整为非0数值(如1积分、2积分、5积分等)。这是平台系统的自动行为,而非作者本人的设定。 因此,如果你当前看到该资源的下载所需积分不是0(例如显示为1、2、3……),请谨慎决定是否下载。 如果你按照非0积分支付并下载后发现资源内容不符合预期、链接失效,或者实际上该资源本应是免费的,作者无法为此承担积分损失或退还操作。强烈建议:仅在页面显示为0积分时进行下载。 另外,本资源描述中并未直接提供具体的下载地址或外部链接,因为它本身是一个通过CSDN官方上传通道提交的文件/内容包。如果你看到描述中没有外部网盘地址,这是正常的——资源文件应通过CSDN内置的“下载”按钮获取。若因平台积分显示异常导致你支付了积分,请优先联系CSDN客服咨询积分退还政策,作者没有权限修改平台自动设定的积分值。 感谢你的理解与支持。技术分享本应开放,但受限于平台规则,特此提醒如上。祝学习进步!
因为工作需要,每天需要打很多次卡,然后忙起来就忘了,忙完了就会想,刚才打卡了吗?弄错就会漏打卡了,漏打卡会有处罚。就想到写一个程序来解决这个痛点。就有了本次发布的这个程序。 PHP项目,修改起来也简单,也方便二开。本来就是H5页面布局,部署好,直接手机浏览器打开,或者使用封装工具,封装成apk。本人已打包为微信小程序,使用起来很方便。 项目简介 本项目是一个多用户打卡记录系统,基于 PHP + MySQL 开发,提供简洁的用户打卡功能和记录管理。 核心功能 功能模块 描述 用户认证 支持用户注册、登录、密码修改、密码重置 打卡功能 用户可进行每日打卡,记录打卡时间 记录查询 支持按日期查询打卡记录 用户管理 支持头像上传、个人信息查看 数据统计 提供打卡统计功能 技术特点 轻量级架构:纯 PHP 开发,无需框架依赖,部署简单 响应式设计:移动端友好的 UI 界面,支持触摸操作 安全性: 使用 prepare + bind_param 防止 SQL 注入 密码采用哈希加密存储 Session 会话管理用户状态 模块化设计:API 接口与前端分离,便于扩展 项目结构 Plain Text ├── api/ # RESTful API 接口 │ ├── checkin.php # 打卡接口 │ ├── login.php # 登录接口 │ ├── register.php # 注册接口 │ ├── records.php # 记录查询接口 │ ├── stats.php # 统计接口 │ └── … ├── config/ # 配置文件 │ ├── database.php # 数据库配置 │ └── auth.php # 认证配置 ├── sql/ # 数据库脚本 │ └── init.sql # 初始化脚本 ├── avatars/ # 头像存储目录 ├── ind
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值