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() 函数。

所以工作流程是:

  1. 用户打开页面,@app.route('/')函数执行,正在加载页面。
  2. 正在加载页面获取 @app.route('/create_map') 并在后台运行其功能。
  3. 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>