Flask -显示正在加载的页面,而另一个耗时的函数正在运行



大家好。我正在开发我的第一个flask项目,我遇到了以下问题:

我有一个简单的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的新手,如果你能给我一个好的解释,我将非常感激。

谢谢! !

我终于找到解决办法了!

感谢Laurel的回答。我把它写得更漂亮更清楚。

我做了什么

我重新设计了我的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>

然后,在<body>部分添加一个加载轮div:

<body>
<div class="loader"></div>
</body>

如果你仍然不清楚-请检查我的例子在答案的末尾

<script>部分,我们必须声明navigate()函数。它只是将用户重定向到所需的引用,在本例中是/map

fetch()jQuery.ajax()的类似物-了解更多。它只是获取到/create_map的应用程序路由,等待它在"后台"中完成,然后在.then()块中执行操作——在我们的例子中是navigate()函数。

所以工作流是:

  1. 用户打开页面,执行@app.route('/')功能,正在加载页面
  2. 加载获取@app.route('/create_map')的页面并在后台运行其功能。
  3. create_map()函数完成时,用户被重定向到@app.route('/map')函数,该函数正在渲染所有完成的map.html模板。

我的一些建议

  • 如果你想让你的加载页面有一个图标,只需添加以下选项卡到loading.html<head>部分:
<link rel="icon" href="/static/<icon_file>">

注意, Flask正在搜索/static文件夹中的媒体。把你的媒体放进去。否则,媒体将不被渲染!

  • 如果你想让你的加载页面有一个漂亮的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>

最新更新