Reload Flask app when template file changes

默认情况下,当使用内置服务器(Flask.run)运行 Flask 应用程序时,它会监视 Python 文件,并在代码发生变化时自动重新加载应用程序:

* Detected change in '/home/xion/hello-world/app.py', reloading
* Restarting with reloader

不幸的是,这似乎只适用于 * 文件,而且我似乎没有找到任何方法将此功能扩展到其他文件。最值得注意的是,当 模板发生变化时,让 Flask 重新启动应用程序将非常有用。我已经记不清自己有多少次在模板中摆弄标记,因为没有看到任何更改而感到困惑,结果发现这个应用程序仍在使用旧版的金贾模板。

那么,是否有办法让 Flask 监视器文件位于 模板目录中,还是需要深入到框架的源代码中?

编辑 : 我正在使用 Ubuntu 10.10,实际上还没有在其他平台上尝试过。


经过进一步的调查,我发现模板的变化的确是 are实时更新,而没有重新加载应用程序本身。然而,这似乎只适用于那些传递给 flask.render_template的模板。

但碰巧的是,在我的应用程序中,我有相当多的可重用的,参数化的组件,我在金贾模板中使用它们。它们作为 {% macro %}实现,驻留在专用的“模块”中,并被 {% import %}分为实际的页面。所有漂亮和干燥... 除了那些导入的模板显然从来没有检查修改,因为他们不通过 render_template在所有。

(奇怪的是,通过 {% extends %}调用的模板不会发生这种情况。至于 {% include %},我不知道,因为我并不真正使用它们。)

总而言之,这种现象的根源似乎在金贾和 Flask 或 Werkzeug 之间的某个地方。我想这可能值得为这两个项目中的任何一个进行 bug 跟踪:)与此同时,我已经接受了 JD.的回答,因为这是我实际使用的解决方案——而且它工作起来像魔法一样。

128018 次浏览

在 Windows 上使用 Flask 的最新版本,使用 run 命令并将 debug 设置为 true; Flask 不需要重置就可以使对模板的更改生效。尝试 Shift + F5(或 Shift + 重新加载按钮) ,以确保没有任何东西被缓存。

In my experience, templates don't even need the application to restart to be refreshed, as they should be loaded from disk everytime render_template() is called. Maybe your templates are used differently though.

要在模板改变(或任何其他文件)时重新加载应用程序,您可以将 extra_files参数传递给 Flask().run(),这是要观察的文件名集合: 对这些文件的任何更改都将触发重新加载程序。

例如:

from os import path, walk


extra_dirs = ['directory/to/watch',]
extra_files = extra_dirs[:]
for extra_dir in extra_dirs:
for dirname, dirs, files in walk(extra_dir):
for filename in files:
filename = path.join(dirname, filename)
if path.isfile(filename):
extra_files.append(filename)
app.run(extra_files=extra_files)

See here: http://werkzeug.pocoo.org/docs/0.10/serving/?highlight=run_simple#werkzeug.serving.run_simple

你可以利用

TEMPLATES_AUTO_RELOAD = True

From http://flask.pocoo.org/docs/1.0/config/

是否检查模板源的修改并自动重新加载它。默认情况下,值为 Nothing,这意味着 Flask 只在调试模式下检查原始文件。

实际上对我来说 TEMPLATES_AUTO_RELOAD = True不工作(0.12版本)。我使用 jinja2和我所做的:

  1. 创建函数 before_request

    def before_request():
    app.jinja_env.cache = {}
    
  2. Register it in application

    app.before_request(before_request)
    
  3. That's it.

对我有效的方法就是加上这个:

@app.before_request
def before_request():
# When you import jinja2 macros, they get cached which is annoying for local
# development, so wipe the cache every request.
if 'localhost' in request.host_url or '0.0.0.0' in request.host_url:
app.jinja_env.cache = {}

(taken from @dikkini's answer)

在使用 jinja模板时,需要设置一些参数。在 python3中,我用以下代码解决了这个问题:

if __name__ == '__main__':
app.jinja_env.auto_reload = True
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.run(debug=True, host='0.0.0.0')

请参见 http://flask.pocoo.org/docs/1.0/quickstart/ and use FLASK_ENV=development

您需要在应用程序配置中将 TEMPLATES_AUTO_RELOAD属性设置为 True:

from flask import Flask


app = Flask(__name__)
app.config["TEMPLATES_AUTO_RELOAD"] = True

详情请看 http://flask.pocoo.org/docs/1.0/config/

截至2021年3月更新:

对于运行开发服务器,推荐使用 烧瓶 CLI而不是 app.run () ,因此如果我们想使用 CLI,那么就不能使用公认的解决方案。

在 Flask 1.1或更高版本中,环境变量 FLASK_RUN_EXTRA_FILES或者选项 --extra-files实际上做了与接受的答案相同的事情。参见 这个 Github 问题

Example usage:

flask run --extra-files "app/templates/index.html"
# or
export FLASK_RUN_EXTRA_FILES="app/templates/index.html"
flask run

例如 若要指定多个额外文件,请使用冒号分隔文件路径。

export FLASK_RUN_EXTRA_FILES="app/templates/index.html:app/templates/other.html"

还支持整个目录:

flask run --extra-files app/templates/

模板是自动重新加载的,为什么不做 ctrl+f5刷新网页, 导致浏览器通常保存缓存。

为了在浏览器的服务器 AND 上重新加载应用程序,我使用了 livereload包。通过 CLI 安装

$ pip install livereload

运行代码

from flask import Flask, render_template


app = Flask(__name__)


@app.route("/")
def hello():
return render_template("index.html")


if __name__ == '__main__':
from livereload import Server
server = Server(app.wsgi_app)
server.serve(host = '0.0.0.0',port=5000)

所有的答案在这里使用 extra_files参数或 TEMPLATES_AUTO_RELOAD配置工作,以重新加载它在服务器上,但为了顺利的开发经验,而不损坏您的键盘的 F5键我会与 livereload

我也遇到了同样的麻烦。不过解决方法很简单:

if __name__ == '__main__':
app.jinja_env.auto_reload = True
app.config["TEMPLATES_AUTO_RELOAD"] = True
app.run(debug=True)

放下

app.jinja_env.auto_reload = True
app.config["TEMPLATES_AUTO_RELOAD"] = True

above the main function. So final output for example:

from flask import Flask, app,render_template


app= Flask(__name__)
app.jinja_env.auto_reload = True
app.config["TEMPLATES_AUTO_RELOAD"] = True


@app.route('/')
def index():
return render_template('index.html')


if __name__ == '__main__':
app.run(debug=True)