Flask应用中如何从任意位置便捷引用同目录模板?
解决Flask组件模板便捷引用的方案
我来帮你搞定这个Flask模板引用的麻烦事儿!默认情况下render_template确实只会从根目录的templates文件夹找模板,在子组件里每次都要写长路径实在烦人,这里有几个实用的办法,你可以根据项目情况选:
方法1:用Blueprint(首推,符合Flask模块化设计)
把你的thing组件做成一个Flask Blueprint,让它自带自己的模板目录,这样就能直接引用同目录的模板了,这也是Flask官方推荐的模块化方式,适合长期维护的项目。
步骤很简单:
- 先改
src/thing/__init__.py,创建Blueprint的时候指定模板目录为当前文件夹:
from flask import Blueprint # template_folder='.' 告诉Blueprint,我的模板就在当前目录(src/thing)里 thing_bp = Blueprint('thing', __name__, template_folder='.')
- 然后在
app.py里注册这个Blueprint:
from flask import Flask from src.thing import thing_bp app = Flask(__name__) # 把组件蓝图注册到主应用 app.register_blueprint(thing_bp)
- 最后在
component.py里,直接调用同目录的模板就行:
from flask import render_template from . import thing_bp class ThingComponent: def render(self): # 直接写'component.html'就行,Blueprint会自动从自己的模板目录找 return render_template('component.html', some_var='你好呀')
要是你的组件有路由视图,直接在Blueprint里定义就行,模板引用同样方便。
方法2:给Flask应用加额外模板目录
要是不想用Blueprint,也可以直接把组件的模板目录加到Flask的模板搜索路径里。
修改app.py:
from flask import Flask import os from jinja2 import FileSystemLoader app = Flask(__name__) # 拿到src/thing目录的绝对路径 thing_template_dir = os.path.join(os.path.dirname(__file__), 'src', 'thing') # 把原来的templates目录和组件目录一起传给模板加载器 app.jinja_loader = FileSystemLoader([app.template_folder, thing_template_dir])
之后在component.py里直接写render_template('component.html')就可以了,Flask会自动在新增的目录里找模板。
要是你有好多组件,可以遍历src下的所有子目录,一次性把它们都加进去:
src_dir = os.path.join(os.path.dirname(__file__), 'src') template_dirs = [app.template_folder] # 遍历src下的所有子目录,都加到模板路径里 for root, dirs, files in os.walk(src_dir): template_dirs.append(root) app.jinja_loader = FileSystemLoader(template_dirs)
方法3:自己读模板文件渲染
要是不想改主应用的配置,也可以在组件里自己读取模板文件,用render_template_string来渲染,这种方式组件完全独立,适合小型组件或者不想动主应用的场景。
在component.py里这么写:
from flask import render_template_string import os class ThingComponent: def __init__(self): # 拿到当前组件文件所在的绝对目录 self.current_dir = os.path.dirname(os.path.abspath(__file__)) # 读取同目录下的component.html内容 template_path = os.path.join(self.current_dir, 'component.html') with open(template_path, 'r', encoding='utf-8') as f: self.template_content = f.read() def render(self, **context): # 用render_template_string渲染,把需要的变量传进去就行 return render_template_string(self.template_content, **context)
调用的时候直接:
component = ThingComponent() return component.render(name='Alex')
内容的提问来源于stack exchange,提问作者Alexander Kleinhans
相关产品推荐
相关产品推荐

