Flask - 显示加载页面,而另一个耗时的函数是 运行
Flask - show loading page while another time consuming function is running
大家好。我正在开发我的第一个烧瓶项目,但遇到了以下问题:
我有一个简单的 Flask 应用程序:
from flask import Flask, render_template
import map_plotting_test as mpt
app = Flask(__name__)
@app.route('/')
def render_the_map():
mpt.create_map()
return render_template("map.html")
if __name__ == '__main__':
app.run(debug=True)
问题
mpt.create_map()
函数在这里只是制作地图,渲染它,然后创建 map.html
文件并将其保存到模板文件夹:templates/map.html
。它工作得很好,但是完成地图制作需要一些明显的时间(大约 10-15 秒)。
问题是,在执行此功能时,我在浏览器中看到的只是一个空白屏幕,然后 Flask 才渲染完成的 map.html
文件。
我想要的
我想要做的是在 create_map()
功能为 运行 时显示加载屏幕而不是空白屏幕。当函数完成其工作并创建一个 map.html 文件时 - 像 return render_template("map.html")
一样向用户显示呈现的模板。
有没有办法不费吹灰之力就能做到?我是 Flask 的新手,如果有很好的解释,我将不胜感激。
谢谢!!!
终于找到解决办法了!
Thanks to Laurel's answer. I'll just make it more nice and clear.
我做了什么
我重新设计了我的 Flask 应用程序,所以它看起来像这样:
from flask import Flask, render_template
import map_plotting_module as mpm
app = Flask(__name__)
@app.route('/')
def loading():
return render_template("loading.html")
@app.route('/map')
def show_map():
return render_template("map.html")
@app.route('/create_map')
def create_map():
mpm.create_map()
return "Map created"
if __name__ == '__main__':
app.run()
当用户打开页面时,Flask 开始呈现 loading.html
文件。
在此文件中,您必须将以下代码添加到 <head>
部分:
<script>
function navigate() {
window.location.href = 'map'; // Redirects user to the /map route when 'create_map' is finished
}
fetch('create_map').then(navigate); // Performing 'create_map' and then calls navigate() function, declared above
</script>
然后,将载重轮 div 添加到您的 <body>
部分:
<body>
<div class="loader"></div>
</body>
如果您仍然不清楚 - 请查看答案末尾的示例
说明
在 <script>
部分我们必须声明 navigate()
函数。它只是将用户重定向到所需的引用,在当前情况下为 /map
。
fetch()
类似于 jQuery.ajax()
- read more。它只是获取到 /create_map
的应用程序路由,等待它在“后台”完成,然后在 .then()
块中执行操作 - 在我们的例子中是 navigate()
函数。
所以工作流程是:
- 用户打开页面,
@app.route('/')
函数执行,正在加载页面。
- 正在加载页面获取
@app.route('/create_map')
并在后台运行其功能。
- 当
create_map()
函数完成时 - 用户被重定向到 @app.route('/map')
函数正在呈现 all-done map.html
模板。
我的推荐很少
- 如果您希望加载页面有图标,只需将以下选项卡添加到
loading.html
的 <head>
部分:
<link rel="icon" href="/static/<icon_file>">
Pay attention, Flask is searching for media in the /static
folder. Put your media in it. Otherwise, media will not be rendered!
- 如果您希望您的加载页面有一个不错的 CSS 加载程序,请考虑访问此页面:loading.io。我真的很喜欢它。
最后,这里是加载程序示例的代码片段:
.loader {
position: absolute;
top: 50%;
left: 50%;
margin: -56px 0 0 -56px;
}
.loader:after {
content: " ";
display: block;
width: 110px;
height: 110px;
border-radius: 50%;
border: 1px solid;
border-color: #0aa13a transparent #47a90e transparent;
animation: ring 1.2s linear infinite;
}
@keyframes ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Loading...</title>
</head>
<body>
<div class="loader"></div>
</body>
</html>
大家好。我正在开发我的第一个烧瓶项目,但遇到了以下问题:
我有一个简单的 Flask 应用程序:
from flask import Flask, render_template
import map_plotting_test as mpt
app = Flask(__name__)
@app.route('/')
def render_the_map():
mpt.create_map()
return render_template("map.html")
if __name__ == '__main__':
app.run(debug=True)
问题
mpt.create_map()
函数在这里只是制作地图,渲染它,然后创建 map.html
文件并将其保存到模板文件夹:templates/map.html
。它工作得很好,但是完成地图制作需要一些明显的时间(大约 10-15 秒)。
问题是,在执行此功能时,我在浏览器中看到的只是一个空白屏幕,然后 Flask 才渲染完成的 map.html
文件。
我想要的
我想要做的是在 create_map()
功能为 运行 时显示加载屏幕而不是空白屏幕。当函数完成其工作并创建一个 map.html 文件时 - 像 return render_template("map.html")
一样向用户显示呈现的模板。
有没有办法不费吹灰之力就能做到?我是 Flask 的新手,如果有很好的解释,我将不胜感激。
谢谢!!!
终于找到解决办法了!
Thanks to Laurel's answer. I'll just make it more nice and clear.
我做了什么
我重新设计了我的 Flask 应用程序,所以它看起来像这样:
from flask import Flask, render_template
import map_plotting_module as mpm
app = Flask(__name__)
@app.route('/')
def loading():
return render_template("loading.html")
@app.route('/map')
def show_map():
return render_template("map.html")
@app.route('/create_map')
def create_map():
mpm.create_map()
return "Map created"
if __name__ == '__main__':
app.run()
当用户打开页面时,Flask 开始呈现 loading.html
文件。
在此文件中,您必须将以下代码添加到 <head>
部分:
<script>
function navigate() {
window.location.href = 'map'; // Redirects user to the /map route when 'create_map' is finished
}
fetch('create_map').then(navigate); // Performing 'create_map' and then calls navigate() function, declared above
</script>
然后,将载重轮 div 添加到您的 <body>
部分:
<body>
<div class="loader"></div>
</body>
如果您仍然不清楚 - 请查看答案末尾的示例
说明
在 <script>
部分我们必须声明 navigate()
函数。它只是将用户重定向到所需的引用,在当前情况下为 /map
。
fetch()
类似于 jQuery.ajax()
- read more。它只是获取到 /create_map
的应用程序路由,等待它在“后台”完成,然后在 .then()
块中执行操作 - 在我们的例子中是 navigate()
函数。
所以工作流程是:
- 用户打开页面,
@app.route('/')
函数执行,正在加载页面。 - 正在加载页面获取
@app.route('/create_map')
并在后台运行其功能。 - 当
create_map()
函数完成时 - 用户被重定向到@app.route('/map')
函数正在呈现 all-donemap.html
模板。
我的推荐很少
- 如果您希望加载页面有图标,只需将以下选项卡添加到
loading.html
的<head>
部分:
<link rel="icon" href="/static/<icon_file>">
Pay attention, Flask is searching for media in the
/static
folder. Put your media in it. Otherwise, media will not be rendered!
- 如果您希望您的加载页面有一个不错的 CSS 加载程序,请考虑访问此页面:loading.io。我真的很喜欢它。
最后,这里是加载程序示例的代码片段:
.loader {
position: absolute;
top: 50%;
left: 50%;
margin: -56px 0 0 -56px;
}
.loader:after {
content: " ";
display: block;
width: 110px;
height: 110px;
border-radius: 50%;
border: 1px solid;
border-color: #0aa13a transparent #47a90e transparent;
animation: ring 1.2s linear infinite;
}
@keyframes ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Loading...</title>
</head>
<body>
<div class="loader"></div>
</body>
</html>