我在 Flask 中使用 a jinja2.ChoiceLoader
(也尝试了多条路径FileSystemLoader
,没有快乐)有一个相当奇怪的问题。
我有几个“主题”目录,就像这样。
/templates/
themes/
default/
layout.html
menu.html
blue/
layout.html
grey/
menu.html
...
default/
如果所选主题没有所需的模板,我想回退到,所以我使用了 ChoiceLoader,就像这样。
@app.before_request
def setup_request():
current_theme = get_theme()
logging.info('Using theme %s'%(current_theme))
app.jinja_loader = jinja2.ChoiceLoader([
jinja2.FileSystemLoader('/templates/themes/%s/'%(current_theme)),
jinja2.FileSystemLoader('/templates/themes/default/')
])
太好了,但是如果我更改它,<current_theme>
它仍然会从旧文件夹加载主题,直到我重新加载 Apache 或重新启动 Flask 开发服务器。
它应该使用新主题。日志记录说它正在使用更改后的主题,但显然app.jinja_loader
有点像蜜獾……在我重新加载 Apache 之前,它完全忽略了它。
编辑:考虑到所有同名文件都是同一个文件,这似乎与 Flask 有关。我可以使用内置服务器(使用 DEBUG=True)、Cherry 和 mod_wsgi 进行重现。这个人似乎有类似的问题,但没有简单的解决方案:flask blueprint template folder我的情况不同,因为我需要为单个应用程序级联模板。他的问题与蓝图之间的级联模板有关,但实际上可能是同一个问题。
这是“get_theme()”调用中的代码:
def get_theme():
# I know this is unsafe, testing only
return request.args.get('theme','default')
编辑 2:我需要更改主题之间的 HTML 和 JavaScript,而不仅仅是 CSS。这就是为什么我不只是加载不同的 CSS 文件。此外,其中一些主题适用于移动设备,与其他主题几乎没有共同之处。
编辑3:两种解决方案。解决方案 1:对文件进行唯一命名,例如“blue.layout.html”和“default.layout.html”。这完美地工作,但它没有按要求级联。解决方案 2:使用相对路径,所以不要include 'file.html'
使用include 'theme/blue/file.html
. 我通过创建一个get_theme_file()
检查活动主题、检查文件是否存在(如果不存在,则回退到“默认”主题)并返回相对路径的函数来实现级联。我只需要确保我包含的所有内容看起来像{% include get_theme_file('file.html') %}
. 这并不优雅,但我发现这里使用的 Flask 的低级摆弄更优雅。