1. 静态文件的使用
在一个web项目中,静态文件是必不可少的东西,那么在flask中,有哪些方式可以加载静态文件呢?
在我们新建一个项目的时候,flask就会默认给我们生成一个static
的文件夹,我们的静态文件就就是写在这个文件夹里面的。
假设我们的static
目录结构是这样的。
然后每个文件对应代码为:
- index.css
body{
background: pink;
}
- index.js
alert('hello world');
- 然后我们在
templates
文件夹下面新建一个index.html
的文件。写入代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>static demo</title>
<!-- 使用url_for加载静态文件 url_for第一个参数必须是'static',然后后面跟一个关键字参数filename='文件路径',从static文件夹下面开始寻找的 -->
<link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}">
<!-- 使用url加载静态文件,以/开头的,浏览器会自动将前面的域名,端口号补齐 -->
<!-- <link rel="stylesheet" href="/static/css/index.css"> -->
<!-- 使用相对路径导入静态文件? 真的可以这样导入吗? -->
<script src="../static/js/index.js"></script>
<!-- <script src="{{ url_for('static',filename='js/index.js') }}"></script> -->
</head>
<body>
<p>static demo</p>
<img src="{{ url_for('static',filename='images/test.png') }}" alt="" width="500px" height="500px">
<!-- <img src="../static/images/test.png" alt="" width="500px" height="500px"> -->
</body>
</html>
- 然后我们在app.py中创建一个函数视图,渲染这个
index.html
页面,就能够查看到效果了。
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
在上面的index.html
中,我们使用了3种方式加载静态文件,分别是url_for
,url方式
,相对路径
三种方式。接下来我们来说一下他们的查找路径。
url_for
:url_for默认是从项目的根目录下面的static
文件夹下面去寻找,我们也可以自己指定static
文件夹的位子,只需要我们在初始化app的时候,添加一个参数就可以了. 即在app.py中,app = Flask( __name__,static_folder=r'D:\static' )
,这样,我们就将我们static文件夹侧存放位置改变到D:\static
下面去了,那么以后寻找使用url_for
寻找静态文件得时候,就会去这个线面寻找。当然,我们在项目的开发过程中,一般都不会去修改static
的默认位置。使用默认的就可以了。url的方式
:其实我们使用url_for
的时候,得到的就是静态文件对应的url,所以使用url的方式的查找路径和url_for
方式的查找路径都是一样的,不过需要注意的是,为什么url是以static
开始呢,然后后面是静态文件对应static
文件夹的相对路径呢,这也是因为flask
默认就是使用的static
作为静态文件的path,我们也是可以改变的,也是在app进行初始化的时候,传入一个参数就可以了.app = Flask(__name__,static_url_path='/static_demo/')
。改变之后,那么我们以后在模板中加载静态文件使用url的方式,就得变成/static_demo/<静态文件相对于static的相对路径>
.这个时候其实我们也可以按f12
查看源码,我们会发现url_for
的方式得到的url也发生的变化,变成了/static_demo/
为前缀的url了。相对路径
:我们在上面的方式中使用的相对路径导入图片,好像是成功了的,但是我们修改了static_url_path
参数的时候,就会发现使用相对路径导入的静态文件全部加载不进来?这是怎么回事呢?这是因为flask其实是不支持使用相对路径导入静态文件,在src属性中,看似我们写的是相对路径,但是flask也认为他是一个url
的方式。首先他会将前面的../..
这些东西去掉,然后再当成url来使用,所以我们不管在src里面写多少个../../../
都是没有用的。这也就能解释为什么我们修改了static_url_path
参数的时候,静态文件的方式就不能导入了。因为他将我们的src的值当做url来解析的,而我们的static_url_path
又被改变了,所以当然就找不到我们的静态文件了。绝对路径
:在flask中,也不支持绝对路径导入的。
一般在项目的开发中,我们都不会去修改static_folder
和static_url_path
这两个值得,使用默认的就好了,这里只是为了说清楚原理。导入静态文件我们一般也使用url_for
的方式。
2. {% include %} 标签
在项目的开发过程中,有很多页面的某些内容都是一样的,比如页面的导航条,页脚的部分,在每个页面都是一样的,如果我们在每个页面都去写这些相同的代码,不仅让我们不好维护代码,也不方便我们修改。这个歌时候我们就可以使用{% include %}
标签了。
首先我们在templates文件夹里面新建两个html文件.
- header.html
<style>
.nav ul{
overflow: hidden;
}
.nav ul li{
float: left;
margin: 0 20px;
}
</style>
<nav class="nav">
<ul>
<li>首页</li>
<li>课程详情</li>
<li>教程视频</li>
<li>关于我们</li>
</ul>
</nav>
- footer.html
<h1>footer</h1>
这样,我们就相当于将header和footer部分的代码抽取了出来,然后我们需要的时候就直接导入就可以了。
在templates里面新建一个index.html
文件,写入代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>include tag demo </title>
</head>
<body>
<!-- 导入header.html -->
{% include 'header.html' %}
<div class="content">
中间内容
</div>
<!-- 导入footer.html -->
{% include 'footer.html' %}
</body>
</html>
然后我们在app.py中对index.html
进行映射,然后再浏览器中输入对应的url,就能够查看到相应的效果了。
这样,我们就像header和footer抽取了出来,以后我们想使用的时候,我们就直接{% include %}
一下就可以了。
3. {% extends %}标签
在上面{% include %} 标签的demo中,我们也可以使用{% extends %}标签来完成相应的需求。
首先我们新建一个base.html
文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 定义接口,给这个接口取一个名字叫 title -->
<title>{% block title %}{% endblock %}</title>
<style>
.nav ul{
overflow: hidden;
}
.nav ul li{
float: left;
margin: 0 20px;
}
</style>
</head>
<body>
<nav class="nav">
<ul>
<li>首页</li>
<li>课程详情</li>
<li>关于我们</li>
</ul>
</nav>
<!-- 定义接口,给这个接口取一个名字叫 content-->
{% block content %}
<p style="background: red">这是父模板中的代码</p>
{% endblock %}
<footer>
<h1>footer</h1>
</footer>
</body>
</html>
这样,我们先定义好一个父模板base.html
,然后模板中需要变化 的地方我们使用{% block %}
标签定义一个接口,并给不同的接口取相应的名字,方便我们在字模板中使用,例如上面的{% block title %}{% endblock %}
和{% block content %}<p style="background: red">这是父模板中的代码</p>{% endblock %}
然后我们新建一个index.html
的文件,继承base.html
文件。
<!-- 申明继承那个模板,注意这句代码一般都会写在html文件的最上面 -->
{% extends 'base.html' %}
<!-- 调用title接口,编写里面的内容 -->
{% block title %}
index
{% endblock %}
<!-- 调用content接口,编写里面的内容 -->
{% block content %}
<h1 style="background: green">index 子模板</h1>
{% endblock %}
然后,我么在app.py文件对index.html
添加映射,输入url,就能够查看到效果了。
在上面的父模板中定义的接口中,{% block content %} 接口在父模板中石油内容的,而当我们渲染出来发现是没有父模板中的内容的,这是因为flask默认是不会显示父模板中的内容的,如果我们想显示父模板中的内容,使用super()
函数就可以拿到父模板中的内容了,我们还想拿到title接口
中的内容,就可以使用self.title()
,就能拿到title接口
中的内容了
<!-- 调用content接口,编写里面的内容 -->
{% block content %}
<!-- 拿到父模板中的内容 -->
{{ super() }}
<!-- 拿到title接口中的内容 -->
{{ self.title() }}
<h1 style="background: green">index 子模板</h1>
{% endblock %}
总结:
- 使用{% extends %}标签之后,那么就只能将代码写在
{% block %}
提供的接口中,写在其他地方的代码是不会别渲染显示的 - 使用
{{ super() }}
可以拿到父模板中的内容 - 使用
{{ self.title() }}
可以拿到另外一个模块title中的内容