这并不完美,但我正在尝试以下方法。我有一个装饰器:
def early_flush_of_head(template_name):
def wrapper(original_view_function):
@wraps(original_view_function)
def new_view_function(*args, **kwargs):
def streamer():
yield render_template(template_name, head_only=True)
yield original_view_function(*args, **kwargs)
return Response(stream_with_context(streamer()))
return new_view_function
return wrapper
您可以使用它来装饰给定的视图,如下所示:
@app.route('/')
@early_flush_of_head('template.html')
def index():
data = something_time_consuming() # DB traffic or maybe some crazy calculations
return render_template('template.html', data=data)
每个 template.html 看起来像这样:
{% extends "base.html" %}
{% block pre_flush_head %}
<link href="static/css/page.min.css" rel="stylesheet">
<script src="static/js/page.min.js"></script>
{% endblock %}
{% block post_flush_head %}
<title>{{ page_name }}</title>
{% endblock %}
{% block content %}
The actual page.
{% endblock %}
base.html 看起来像这样:
{% if head_only %}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="static/css/common.min.css" rel="stylesheet">
<script src="static/js/common.min.js"></script>
{% else %}
{% block post_flush_head %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
{% endif %}
每个模板实际上被渲染两次。一次在 head_only=True 的装饰器中,然后在真实视图函数中再次没有定义。另请注意,我没有冲洗整个头部,头部有一些东西但仍然需要来自真实视图功能的数据。如果您根据数据命名页面,标题就是一个很好的例子。
这里有一些改进的余地(我不喜欢你必须两次输入模板的名称,这总体上有点侵入性),但它确实让你受益于提前冲洗(使确保您的部署环境不会在您不知情的情况下缓冲)。