flask模板结构组织(局部模板、宏、模板继承)
模板结构组织
除了使用函数、过滤器等工具控制模板的输出外,jinja2还提供了一些工具来在宏观上组织模板内容。
局部模板
在Web程序中,我们通常会为每一类页面编写一个独立的模板。比如主页模板、用户资料也模板、设置页模板等。这些模板可以直接在视图函数中渲染并作为HTML响应主题。除了这类模板,我们还会用到另一类非独立模板,这类模板通常被称为局部模板或此模板,因为它们仅包含部分代码,所以我们不会在视图函数中直接渲染它,而是插入到其他独立模板中。
当某个视图用来处理ajax请求时,返回的数据不需要包含完整的HTML结构,这时就可以返回渲染后的局部模板。
当多个独立的模板中都会使用同一块HTML代码时,我们可以把这部分代码抽离出来,存储到局部模板中。这样一方面可以避免重复,另一方面也可以方便统一管理。比如,多个页面中都要在页面顶部显示一个提示条,这个横幅可以定义在局部模板_banner.html中。
我们使用include标签来插入一个局部模板,这会把局部模板的全部内容插在使用include标签的位置。
比如在其他模板中,我们可以在任意位置使用下面的代码插入_banner.html的内容:
{% include ‘_banner.html’ %}
为了和普通模板区分开,局部模板的命名通常以一个下划线开始。
宏
宏(macro)是jinja2提供的一个非常有用的特性,它类似python中的函数。使用宏可以把一部分模板代码封装到宏里,使用传递的参数来构建内容,最后返回构建后的内容。在功能上,它和局部模板类似,都是为了方便代码块的重用。
为了便于管理,可以把宏存储在单独的文件中,这个文件通常命名为macros.html或_macros.html。在创建宏时,使用macro和endmacro标签声明宏的开始和结束。在开始标签中定义宏的名称和接收的参数
例子:
{% macro qux(amount=1) %}
{% if amount == 1 %}
I am qux.
{% elif amount > 1 %}
We are quxs.
{% endmacro %}
使用时,需要向从python模块中导入函数一样使用import语句导入它,然后作为函数调用,传入必要的参数,例如:
{% from 'macros.html' import qux %}
...
{{ qux(amount=5) }}
另外,在使用宏时我们需要注意上下文问题,在jinja2中,出于性能的考虑,并且为了让一切保持显示,默认情况下包含(include)一个局部模板会传递当前上下文到局部模板中,但导入(import)不会。具体来说,当我们使用render_template()函数渲染一个foo.html模板时,这个foo.html的模板上下文中包含下列对象:
1 flask使用内置的模板上下文处理函数提供的g、session、config、request。
2 扩展使用内置的模板上下文处理函数提供的变量。
3 自定义模板上下文处理传入的变量
4 使用render_template()函数传入的变量
5 jinja2和flask内置及自定义全局对象。
6 jinja2内置及自定义过滤器
7 jinja2内置及自定义测试器
使用include标签插入的局部模板(比如_banner.html)同样可以使用上述上下文中的变量和函数。而导入另一个并非直接渲染的模板(比如macro.html)时,这个模板进包含下列这些对象:
1 jinja2和flask内置的全局函数和自定义全局函数
2 jinja2内置及自定义过滤器
3 jinja2内置及自定义测试器
因此,如果我们想在导入的宏中使用第一个列表中的2、3、4项,就需要在导入时显示地使用with context声明传入当前模板的上下文:
{% from “macros.html” import foo with context %}
虽然flask使用内置的模板上下文处理函数传入session、g、request和config,但它同时也使用app.jinja_env.globals字典将这几个变量设置为全局变量,所以我们仍然可以在不显示声明传入上下文的情况下,直接在导入的宏中使用它们。
模板继承
jinja2的模板继承允许你定义一个基模板,把网页上的导航栏、页脚等通用内容放在基模板中,而每一个继承基模板的子模板在被渲染时都会自动包含这些部分。使用这种方式可以避免在多个模板中编写重复的代码。
编写基模板
基模板存储了程序页面的固定部分,通常被命名为base.html或layout.html。实例程序中的基模板base.html中包含了一个基本的HTML结构,我们还添加了一个简单的导航条和页脚
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="utf-8">
<title>{% block title %}Template - HelloFlask{% endblock %}</title>
{% block styles %}{% endblock %}
{% endblock %}
</head>
<body>
<nav>
<ul><li><a href="{{ url_for('index') }}">Home</a></li></ul>
</nav>
<main>
{% block content %}{% endblock %}
</main>
<footer>
{% block footer %}
...
{% endblock %}
</footer>
{% block sripts %}{% endblock %}
</body>
</html>
当子模板继承基模板后,子模板会自动包含基模板的内容和结构。为了能够让子模板方便地覆盖或插入内容到基模板中,我们需要在基模板中定义块(block),在子模板中可以通过定义同名的块来执行继承操作。
块的开始和结束分别使用block和endblock标签声明,而且快之间可以嵌套。在这个基模板中,我们创建了6个块:head、title、styles、content、footer和scripts,分别用来划分不同的代码。其中,head块表示<head>标签的内容,title表示<title>标签的内容,content块表示页面主题内容,footer表示页脚部分,styles块和scripts块分别用来包含CSS文件和javaScript文件引用链接或页内的CSS和javaScript代码。
这里的块名称可以随意指定,而且并不是必须的。你可以按照需要设置块,如果只需要让字模板添加主体内容,那么仅定义一个content块就足够了。
以content块为例,模板继承示意图如下:
为了避免块的混乱,块的结束标签可以指明块名,同时要确保前后名称一致。
如:
{% block body %}
…
{% endblock body %}
编写子模板
因为基模板中定义了HTML的基本结构,而且包含了页脚等固定信息,在子模板中我们不再需要定义这些内容,只需要对特定的块进行修改。这时我们可以修改前面创建的电影清单模板watchlist.html和主页模板index.html,将这些子模板的通用部分合并到基模板中,并在子模板中定义块来组织内容,以便在渲染时将块中的内容插入到基模板的对应位置。
以index.html为例,修改后的index.html子模板如下:
{% extends 'base.html' %}
{% from 'macros.html' import qux %} {% block content %}
{% set name='baz' %}
<h1>Template</h1>
<ul>
<li><a href="{{ url_for('watchlist') }}">Watchlist</a></li>
<li>Filter:{{ foo|musical }}</li>
<li>Global:{{ bar() }}</li>
<li>Test:{% if name is baz %}I am baz.{% endif %}</li>
<li>Macro: {{ qux(amount=5) }}</li>
</ul>
{% endblock %}
我们使用extends标签声明扩展基模板,它告诉模板引擎当前模板继承base.html
extends必须是字模板的第一个标签。
我们在基模板中定义了四个块,在子模板中,我们可以对父模板中的块进行两种操作:
1 覆盖内容
当在字模板里创建同名的块时,会使用子块的内容覆盖父块的内容。比如在字模板index.html中定义了title块,内容为Home,这会把块中的内容填充到基模板里的title块的位置,最终渲染为<title>Home</title>,content块的效果同理。
2 追加内容
如果要向基模板中的块追加内容,需要使用jinja2提供的super()函数进行声明,这会向父块添加内容。比如,下面例子中向基模板中的styles块追加了一行<style>样式定义:
{% block styles %}
{{ super() }}
<style>
.foo{
color:red;
}
</style>
{% endblock %}
当字模板被渲染时,它会继承基模板的所有内容,然后根据我们定义的块进行覆盖或追加操作,渲染子模板index.html的结果:
相当于把base.html的内容先拷贝过来,然后根据子模板中的内容进行定型,比如覆盖了什么块
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Template - HelloFlask}</title>
</head>
<body>
<nav>
<ul><li><a href="/">Home</a></li></ul>
</nav>
<main>
<h1>Template</h1>
<ul>
<li><a href="/watchlist">Watchlist</a></li>
<li>Filter:I am foo.♫</li>
<li>Global:I am bar.</li>
<li>Test:I am baz.</li>
<li>Macro: We are quxs.</li>
</ul>
</main>
<footer>
...
</footer>
</body>
</html>
flask模板结构组织(局部模板、宏、模板继承)的更多相关文章
- Flask之模板之宏、继承、包含
3.5 宏.继承.包含 类似于python中的函数,宏的作用就是在模板中重复利用代码,避免代码冗余. Jinja2支持宏,还可以导入宏,需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有 ...
- Flask基础(15)-->模板代码的复用【宏(Macro)、继承(Block)、包含(include)】
宏 对宏(macro)的理解: 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用 需要在多处重 ...
- 7、Flask实战第7天:Jinjia2模板
Jinja2模板介绍和查找路径 在前面的章节中,视图只是直接返回文本,然而在实际生产环境中其实很少这样用,因为实际的页面大多带有样式和复杂逻辑的HTML代码,这可以让浏览器其渲染出非常漂亮的页面. 我 ...
- WeCenter二次开发教程(一):熟悉模板结构
<1>程序文件目录介绍: app – 应用目录 models – 模型目录 plugins – 插件目录 static – 静态文件 system – 系统目录 views – 模板目录 ...
- Octopus系列之重新规范了模板结构,大家快来看啊
模板结构我是这样来设计的:大家请看,下面四个关键字 frontend[前段]backend[后端]member[会员]widget[部件] 前段页面包括 _Frontend_header_1.html ...
- 简单的Verilog测试模板结构
这里记录一下曾经用到的简单的测试模板,如下所示: //timescale `timescale 1ns/1ns module tb_module(); //the Internal motivatio ...
- 045——VUE中组件之父组件使用scope定义子组件模板结构
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- c++ 模板特化与局部特化
c++ 模板特化与局部特化 模板的由来是要处理泛化,也就是任何类型都可以处理.但是泛化的同时,如果针对某种特殊的类型,又更加效率的处理方法.c++提供针对特殊的类型,可以定义不同的处理方法.针对某种特 ...
- Flask入门很轻松(三)—— 模板
Jinja2模板引擎 转载请在文章开头附上原文链接地址:https://www.cnblogs.com/Sunzz/p/10959471.html Flask内置的模板语言,它的设计思想来源于 Dja ...
随机推荐
- 五、Docker
1.简介 Docker是一个开源的应用容器引擎:是一个轻量级容器技术: Docker支持将软件编译成一个镜像:然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接使用这个镜像: 运行中的这 ...
- Java 堆外内存
入口ByteBuffer.allocateDirect public static ByteBuffer allocateDirect(int capacity) { return new Direc ...
- Linux安装go
在 http://golang.org/dl/下载最新的linux版本,并把它提取到/usr/local目录,在此目录下进行解压缩 $ sudo tar -xzf go1.9.1.linux-amd6 ...
- NYOJ 开心的小明
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> #inc ...
- Redis入门到高可用(五)—— 单线程
一.单线程为何这么快 1)绝大部分请求是纯粹的内存操作(非常快速) 2)采用单线程,避免了不必要的上下文切换和竞争条件 3)非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框 ...
- 截取字符串后几位用 length
- node跨域cors模块,nodejs+express跨域
使用express写的接口,只能在内部使用,如果想要外部的服务访问,就涉及到了跨域.但是又不想用jsonp,其实有一个node模块,可以轻松实现跨域 npm install cors --save 然 ...
- 4.C#虚方法virtual详解
C#虚方法virtual详解 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象的语言当然也不例外. 虚拟函数从C#的程序编译的角度来看,它和其它一般的函数 ...
- 第三章Div水平居中
1.div居中 text-align:center可以让元素里面的文字内容居中,但并不能让div居中.要让div水平居中必须设置div宽度,外边距设置为margin:0 auto <%@ Pag ...
- linux统计文件夹大小
统计总大小: du -sh dirname 统计文件夹内部各文件大小及总大小: du -h dirname