简介
一个web页面有很多模块,这些模块很多是重复的,这时候就可以通过页面组合来调用,而不是每个页面都重复的写一个模块
例如顶部的导航栏,底部的版权信息等,需要在每个页面都展示的模块,都可以直接组合调用使用,无需重复写
本篇文章基于《Python-Web应用-界面跳转》上修改
创建CSS目录以及模块目录
创建CSS目录
在项目目录下面新建一个名称为static的目录,这个目录用于存放CSS文件

创建模块目录
在templates目录下面创建components目录,这个目录用于存放模块

创建骨架文件
在templates目录下创建一个名称为frame.html的文件,这个文件是一个完整的html文件

这个文件写了一个简单的顶部导航栏

调用了外部CSS
<link rel="stylesheet" href="{{ url_for('static', filename='style.css')}}">

<link rel="stylesheet" href="{{ url_for('static', filename='style.css')}}">中的{{ url_for('static', filename='style.css')}}是 Flask 模板中用于生成静态文件 URL 的标准写法。
{{...}}
{{...}}是Jinja2 模板引擎的变量输出语法,双花括号内的表达式会被计算,结果替换到 HTML 中
url_for()
url_for()是Flask 提供的全局函数,用于根据传入的端点(endpoint)和参数反向生成 URL,在模板中可以直接使用,无需额外导入
static
static参数是 Flask 内置的特殊端点名称,指向项目的静态文件目录(默认是项目根目录下的 static 文件夹),当使用 url_for('static', filename='...') 时,Flask会生成指向static目录下指定文件的URL,注意static参数是固定的不能改变的,不能说css文件在css目录下,就可以把static改成css
CSS不在static目录下
如果css文件不在static目录下,那么有两方法可以解决
第一种,在主程序py文件中指定static的目录和路径
这一种方法很简单,直接在app = Flask(__name__)中添加两个参数,一个是static_folder='/css目录路径',另外一个是static_url_path='/css目录路径',然后正常使用href="{{ url_for('static', filename='style.css')}}即可。
第二种是引用蓝图,这种方式适用于大型项目,利用蓝图管理对应模块的路由,css,js等,方便维护,这种方法比较复杂,后面放到单独的一篇文章讲解
filename='style.css'
这个参数是指定css文件,style.css是css文件名称,支持路径方式,例如现在默认的css目录是static,但是你在下面创建了一个css目录,在css目录面创建了一个index.css文件,那么就可以使用指定路径的方式:css/index.css
修改首页(index.html)文件
把之前的index.html文件修改一下,因为创建了骨架文件,这个文件包含了完整的html文件必要模块,那么index.html文件只需要展示首页部分的内容即可
下面就是一个简单的示例文件:
{% extends "frame.html" %}
{% block title %}首页-测试首页{% endblock %}
{% block index_text %}
<h1>测试首页</h1>
{% endblock %}

第一行{% extends "frame.html" %}
{% extends "frame.html" %}是让当前模板采用frame.html也就是创建的骨架文件作为基础布局,只需填写变化的部分。 这是Jinja2实现代码复用、保持页面结构一致的标准方式。
第二行{% block title %}首页-测试首页{% endblock %}
这一行的作用是把首页-测试首页填充进frame.html的完整的html结构里面的<title>标签里面,或者说是替换骨架文件里面的{% block title %}默认标题{% endblock %}
第三、四、五行
{% block index_text %}
<h1>测试首页</h1>
{% endblock %}
这几行的作用是把
{% block index_text %}
{% endblock %}
中间的内容填充到骨架文件里面
创建底部版权文件
创建底部的版权文件也是一样的,因为骨架文件里面有完整的htnl格式,我们只需要编写填充部分即可
下面是一个简单的示例:
<div class="bottom">
这个是底部
</div>

组合页面
回到骨架文件,开始引用填充部分(index.html)以及底部的版权信息模块
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css')}}">
</head>
<body>
<div class="top">
<a href="">
<div class="top_li">
选项一
</div>
</a>
<a href="">
<div class="top_li">
选项二
</div>
</a>
<a href="">
<div class="top_li">
选项三
</div>
</a>
</div>
<main>
{% block index_text %}{% endblock %}
</main>
{% include "components/bottom.html" %}
</body>
</html>
上面是一个简单的完整的骨架文件
因为index.html文件中的{% extends "frame.html" %},也就是说index.html会调用frame.html这个文件并填充对应的block到frame.html中,渲染成一个完整的index.html页面
<title>{% block title %}默认标题{% endblock %}</title>会被替换成index.html中的{% block title %}首页-测试首页{% endblock %}
{% block index_text %}{% endblock %}会被替换成index.html中的
{% block index_text %}
<h1>测试首页</h1>
{% endblock %}
{% include "components/bottom.html" %}则是引入bottom.html文件里面的
<div class="bottom">
这个是底部
</div>
最终的页面效果为

block参数解释
{% block index_text %}{% endblock %}中的index_text是可以自定义的,但是需要被填充的和填充的是一样的
例如我把index.html页面的{% block title %}首页-测试首页{% endblock %}改为{% block title_1 %}首页-测试首页{% endblock %},那么我在frame.html文件中的<title>{% block title %}默认标题{% endblock %}</title>也需要同步改为<title>{% block title_1 %}默认标题{% endblock %}</title>