模板文件更改时重新加载Flask应用

问题:模板文件更改时重新加载Flask应用

默认情况下,使用内置服务器(Flask.run)运行Flask应用程序时,它将监视其Python文件并在代码更改时自动重新加载该应用程序:

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

不幸的是,这似乎仅适用于* .py文件,而且我似乎没有找到任何将此功能扩展到其他文件的方法。最值得注意的是,当模板更改时,让Flask重新启动应用程序将非常有用。我已经迷失了多少次我不喜欢模板中的标记,却因为看不到任何更改而感到困惑,只是发现该应用程序仍在使用旧版本的Jinja模板。

因此,有没有办法在模板目录中包含Flask监视文件,还是需要深入研究框架的源代码?

编辑:我正在使用Ubuntu 10.10。尚未在任何其他平台上尝试过。


经过进一步的查询,我发现模板中的更改确实实时更新的,而无需重新加载应用程序本身。但是,这似乎仅适用于传递给的模板flask.render_template

但是碰巧的是,在我的应用程序中,我有很多在Jinja模板中使用的可重用的,参数化的组件。它们实现为{% macro %}s,驻留在专用的“模块”中,并{% import %}编入实际页面。很好,很干…除了那些导入的模板显然从未检查过是否修改,因为它们根本没有通过render_template

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

因此,总结起来,这种现象的根源似乎在Jinja和Flask或Werkzeug之间。我想对于其中的任何一个项目,都可能需要进行bug跟踪:)同时,我已经接受了jd。的答案,因为这是我实际使用的解决方案-而且它的工作原理很像魅力。

By default, when running Flask application using the built-in server (Flask.run), it monitors its Python files and automatically reloads the app if its code changes:

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

Unfortunately, this seems to work for *.py files only, and I don’t seem to find any way to extend this functionality to other files. Most notably, it would be extremely useful to have Flask restart the app when a template changes. I’ve lost count on how many times I was fiddling with markup in templates and getting confused by not seeing any changes, only to find out that the app was still using the old version of Jinja template.

So, is there a way to have Flask monitor files in templates directory, or does it require diving into the framework’s source?

Edit: I’m using Ubuntu 10.10. Haven’t tried that on any other platforms really.


After further inquiry, I have discovered that changes in templates indeed are updated in real time, without reloading the app itself. However, this seems to apply only to those templates that are passed to flask.render_template.

But it so happens that in my app, I have quite a lot of reusable, parametrized components which I use in Jinja templates. They are implemented as {% macro %}s, reside in dedicated “modules” and are {% import %}ed into actual pages. All nice and DRY… except that those imported templates are apparently never checked for modifications, as they don’t pass through render_template at all.

(Curiously, this doesn’t happen for templates invoked through {% extends %}. As for {% include %}, I have no idea as I don’t really use them.)

So to wrap up, the roots of this phenomenon seems to lie somewhere between Jinja and Flask or Werkzeug. I guess it may warrant a trip to bug tracker for either of those projects :) Meanwhile, I’ve accepted the jd.‘s answer because that’s the solution I actually used – and it works like a charm.


回答 0

以我的经验,模板甚至不需要重新启动应用程序即可刷新,因为每次render_template()调用时都应从磁盘加载模板。也许您的模板使用方式有所不同。

要在模板更改(或其他文件)时重新加载应用程序,可以将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)

参见此处:http : //werkzeug.pocoo.org/docs/0.10/serving/?highlight=run_simple#werkzeug.serving.run_simple

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.

To reload your application when the templates change (or any other file), you can pass the extra_files argument to Flask().run(), a collection of filenames to watch: any change on those files will trigger the reloader.

Example:

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


回答 1

您可以使用

TEMPLATES_AUTO_RELOAD = True

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

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

you can use

TEMPLATES_AUTO_RELOAD = True

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

Whether to check for modifications of the template source and reload it automatically. By default the value is None which means that Flask checks original file only in debug mode.


回答 2

使用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')

When you are working with jinja templates, you need to set some parameters. In my case with python3, I solved it with the following code:

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

回答 3

对我来说效果很好:

 from flask import Flask, render_template, request, url_for, redirect
 app = Flask(__name__)
 app.config["TEMPLATES_AUTO_RELOAD"] = True

请参阅http://flask.pocoo.org/docs/1.0/config/

For me works just fine:

 from flask import Flask, render_template, request, url_for, redirect
 app = Flask(__name__)
 app.config["TEMPLATES_AUTO_RELOAD"] = True

See more on http://flask.pocoo.org/docs/1.0/config/


回答 4

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

  1. 创建功能 before_request

    def before_request():
        app.jinja_env.cache = {}
  2. 在应用程序中注册

    app.before_request(before_request)
  3. 而已。

Actually for me TEMPLATES_AUTO_RELOAD = True does not work (0.12 version). I use jinja2 and what i have done:

  1. Create function before_request

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

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


回答 5

对我有用的只是添加以下内容:

@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 = {}

摘自@dikkini的回答

What worked for me is just adding this:

@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)


回答 6

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

Using the latest version of Flask on Windows, using the run command and debug set to true; Flask doesn’t need to be reset for changes to templates to be brought in to effect. Try Shift+F5 (or Shift plus the reload button) to make sure nothing it being cached.


回答 7

参见http://flask.pocoo.org/docs/1.0/quickstart/ 并使用FLASK_ENV=development


回答 8

截至2019年6月更新:

建议在app.run()上使用烧瓶CLI,以运行开发服务器,因此,如果我们要使用CLI,则不能使用接受的解决方案。

在撰写本文时,使用Flask(1.1)的开发版本允许我们设置环境变量FLASK_RUN_EXTRA_FILES,该变量有效地执行与接受的答案相同的操作。

请参阅此github问题

用法示例:

export FLASK_RUN_EXTRA_FILES="app/templates/index.html"
flask run

在Linux中。要指定多个其他文件,请使用冒号分隔文件路径。,例如

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

CLI还支持--extra-filesFlask 1.1以后的参数。

Updated as of June 2019:

The flask CLI is recommended over app.run() for running a dev server, so if we want to use the CLI then the accepted solution can’t be used.

Using the development version of Flask (1.1) as of this writing allows us to set an environment variable FLASK_RUN_EXTRA_FILES which effectively does the same thing as the accepted answer.

See this github issue.

Example usage:

export FLASK_RUN_EXTRA_FILES="app/templates/index.html"
flask run

in Linux. To specify multiple extra files, separate file paths with colons., e.g.

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

The CLI also supports an --extra-files argument as of Flask 1.1.


回答 9

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

Templates are reloaded automatically, why not doing ctrl+f5 to refresh the webpage, cause web-browsers usually save cache.