Python Flask 编程 | 连载 09 - Jinja2 模板特性

简介: Python Flask 编程 | 连载 09 - Jinja2 模板特性

一、模板的宏

宏,相当于函数,可以把常用功能抽取出来实现重用。HTML 中也会出现重复的代码,将重复的 HTML 代码抽取出来就成为模板的宏,模板的宏是可以写在单独的 HTML 文件中。

模板中的宏的定义需要使用到 macro 关键字。

{% marco 宏的名字%}
<!--HTML代码-->
{% endmarco %}
复制代码

在 templates 文件夹下创建 marco.html 页面,定义并使用宏。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
<form action="">
    <!--定义一个宏-->
    {% macro input(name, type='text', value='')%}
        <div>
            <input class="input-control class2" type="{{ type }}" name="{{ name }}" value="{{ value }}">
        </div>
    {% endmacro %}
    {#  使用宏  #}
    <p>用户名:{{ input('username', value='admin') }}</p>
    {#  密码 password  #}
    <p>密 码:{{ input('password', type='password') }}</p>
</form>
</body>
</html>
复制代码

这里通过宏定义了一个 input 输入框,并定义了一些参数以及设置了默认值。

在 app.py 中定义一个视图函数,该视图函数返回 marco.html 页面

@app.route('/marco')
def marco():
    return render_template('macro.html')
复制代码

重新启动项目,浏览器访问 /marco

image.png

页面中显示了两个输入框,并且第一个输入框显示了设置的默认值,并且 input 框的文本类型也是通过 type 参数传递的类型。

在项目中并不会把宏的定义的代码和调用代码放在一个文件中,将宏的定义保存在 marco.html 页面中中,新建一个 form.html 并且通过 from ... import ... 来导入定义好的宏。

<form action="">
    <h2>导入并使用宏创建登录表单</h2>
    {% from 'macro.html' import input %}
    Username: {{ input('username', value='stark') }}
    Password: {{ input('password', type='password') }}
</form>
复制代码

新建一个视图函数 forms,该函数返回 forms.html。

@app.route('/forms')
def forms():
    return render_template('forms.html')
复制代码

保存代码,浏览器访问 /forms

image.png

二、模板抽象,继承与包含

模板继承

在项目中每个页面都使用了公共的导航栏和底部栏,引用了公共的 js 和 css 等静态文件,这种情况下就可以使用模板的继承,既可以通过 extends 关键字继承一个基本的页面,这个页面中包含了公共的导航栏、静态文件等,在基本页面中使用 block 关键字来定义需要重写的内容。

继承的实现大概分为三个步骤:

  1. 首先在被继承的基本页面中通过 block 关键字定义需要重写的内容
  2. 接着在新的页面中使用 extends 关键字来继承基本页面
  3. 最后就可以在新的页面中通过 block 重写新的内容
  4. 如果有的页面无须重写 block 块的内容,也可以使用 super() 关键字来复用被继承页面中的内容。

在 templates 模板下新建基本页面 base.html,将公共的 html 代码放入 base.html 中,这里通过 block 定义了 title 和 content 两个需要重写的块。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    {% block title %}
    <title>Title</title>
    {% endblock %}
</head>
<body>
    <div class="contain">
        <header>
            页面头部
        </header>
        <article>
            {% block content %}
                主体内容
            {% endblock %}
        </article>
        <footer>
            页面底部
        </footer>
    </div>
</body>
</html>
复制代码

新增 extends.html 并继承 base.html,只需要通过 block 关键字填充中间内容即可

{% extends 'base.html' %}
{% block title %}
<title>第一个继承实现的页面</title>
{% endblock %}
{% block content %}
    <h2>这是重写了 base.html 中的 content 部分的内容</h2>
{% endblock %}
复制代码

新增视图函数 extends。

@app.route('/extends')
def extends():
    return render_template('extends.html')
复制代码

保存代码,并在浏览器中请求 /extends

image.png

此时如果需要修改样式或者引用的文件,只需要修改 base.html 即可,比如修改 base.html 的 header,在 heade 标签中增加 css 样式。

<!--其余代码保持不变-->
<style type="text/css">
    div header {
        background-color: rebeccapurple;
    }
</style>
复制代码

保存代码后,再次访问 /extends

image.png

可以看出 extends.html 页面的头部也随之更改。

当然如果不想重写 base.html 页面中定义的 block 块,也可以使用 super() 关键字来复用 base.html 页面中的内容。

修改 extends.html 页面,复用 base.html 中 content block 块的内容,并增加新的内容。

<!--其余代码保持不变-->
{% block content %}
    <h2>复用 base.html 中的 content 部分的内容</h2>
    {{ super() }}
    <P> 主体内容 2</P>
    <P> 主体内容 3</P>
{% endblock %}
复制代码

保存代码后,再次访问 /extends

image.png

base.html 中 content block 块的内容被保留。

模板包含

include 标签

当公共的模块不是所有的页面都会使用,比如导航条,可能只有一半的页面会使用同一个导航条,这是后就可以将这个导航条单独拆出来到一个页面,相当于定义一个接口,当有页面需要使用这个导航条时,可以使用 include 关键字引入。

使用模板包含大概分为几个步骤:

  1. 首先将只有部分页面才使用的导航栏单独拆到一个页面中
  2. 接着在有需要使用导航栏的页面通过 include 关键字引入

新建一个 side.html 页面,保持只有部分页面使用的导航栏。

<p>这是一个只有部分页面才使用的导航</p>
复制代码

在 extends.html 页面中引入这个导航栏,如果页面不需要就可以不引入。

{% block content %}
    <h2>引入导航栏</h2>
    {% include 'side.html' %}
    <h2>复用 base.html 中的 content 部分的内容</h2>
    {{ super() }}
    <P> 主体内容 2</P>
    <P> 主体内容 3</P>
{% endblock %}
复制代码
保存代码后,再次访问 */extends*。
复制代码

image.png

通过模板的包含引入了在独立页面中定义的导航栏。

继承与包含的区别

继承使用关键字 extends 并使用 block 关键字定义和使用代码块,被继承的页面中包含了所有公共的内容,类似于 Java 中的类或者抽象类,而包含则是使用 include 关键字来引入代码块,相当于接口的定义,并不适用于所有页面,如果有需要可以引入。


相关文章
|
4天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
4天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
4天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
5天前
|
机器学习/深度学习 存储 算法
探索Python编程:从基础到高级应用
【10月更文挑战第38天】本文旨在引导读者从Python的基础知识出发,逐渐深入到高级编程概念。通过简明的语言和实际代码示例,我们将一起探索这门语言的魅力和潜力,理解它如何帮助解决现实问题,并启发我们思考编程在现代社会中的作用和意义。
|
5天前
|
机器学习/深度学习 数据挖掘 开发者
Python编程入门:理解基础语法与编写第一个程序
【10月更文挑战第37天】本文旨在为初学者提供Python编程的初步了解,通过简明的语言和直观的例子,引导读者掌握Python的基础语法,并完成一个简单的程序。我们将从变量、数据类型到控制结构,逐步展开讲解,确保即使是编程新手也能轻松跟上。文章末尾附有完整代码示例,供读者参考和实践。
|
前端开发 JavaScript Java
Flask Web 极简教程(二)- Flask 模板(Part E)
Flask Web 极简教程(二)- Flask 模板(Part E)
Flask Web 极简教程(二)- Flask 模板(Part E)
|
前端开发 Python
Python Flask 简明教程(10)--模板之条件渲染与循环渲染
本文目录 1.前言 2. 条件渲染 3. 循环渲染 4. 小结
496 0
|
前端开发 JavaScript Python
Python Flask 简明教程(9)--模板之渲染变量
本文目录 1. 前言 2. 渲染变量 2.1 普通变量 2.2 字典 2.3 对象 3. 小结
188 0
|
开发框架 Java .NET
Python Flask 简明教程(8)--模板之继承
本文目录 1. 前言 2. 创建项目 3. 创建基模板 4. 继承模板 5. 开发app.py 6. 小结
188 0
|
Web App开发 索引 Python
Flask 教程 第二章:模板
本文转载自:https://www.jianshu.com/p/967e75e6dd5b 在Flask Mega-Tutorial系列的第二部分中,我将讨论如何使用模板。 学习完第一章之后,你已经拥有了一个虽然简单,但是可以成功运行Web应用,它的文件结构如下: microblog\ venv\ app\ __init__.py routes.py microblog.py 在终端会话中设置环境变量FLASK_APP=microblog.py,然后执行flask run命令来运行应用。
1408 0