根据请求标头(HTMX)生成完整页面或 HTML 片段

Bas*_*asj 2 python jinja2 flask htmx

当将 HTMX 框架与 Python Flask 结合使用时,您必须能够:

  • 如果请求是由 HTMX(通过 AJAX)完成的,则将其作为 HTML片段提供服务

  • 如果用户完成请求(例如直接在浏览器 URL 栏中输入),则将请求作为完整页面进行服务器处理

有关更多详细信息,请参阅具有固定页眉/页脚和 HTMX 的单页应用程序,具有浏览 URL 历史记录允许手动页面重新加载 。

如何使用 Flask 模板系统做到这一点?

from flask import Flask, render_template, request
app = Flask("")
@app.route('/pages/<path>')
def main(path):
    htmx_request = request.headers.get('HX-Request') is not None
    return render_template(path + '.html', fullpage=not htmx_request)
app.run()
Run Code Online (Sandbox Code Playgroud)

输出整页的标准方法是什么(基于父模板pagelayout.html):

{% extends "pagelayout.html" %}
{% block container %}
<button>Click me</button>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

iffullpageTrue,并且只是一个 HTML 片段:

<button>Click me</button>
Run Code Online (Sandbox Code Playgroud)

如果是False

Dau*_*ros 6

该解决方案基于我们可以在扩展基本模板时使用动态变量。因此,根据类型或请求,我们使用完整的基本模板或仅返回片段内容的最小基本模板。

让我们调用片段的基本模板base-fragments.html

{% block container %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

它只是返回主块的内容,没有其他内容。在视图函数中,我们有一个新的模板变量baselayout,其中包含基础模板的名称,具体取决于请求的类型(是否源自 HTMX):

@app.route('/pages/<path>')
def main(path):
    htmx_request = request.headers.get('HX-Request') is not None
    baselayout = 'base-fragments.html' if htmx_request else 'pagelayout.html'

    return render_template(path + '.html', baselayout=baselayout)
Run Code Online (Sandbox Code Playgroud)

在页面模板中,我们baselayout在以下位置使用此变量extends

{% extends baselayout %}
{% block container %}
<button>Click me</button>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)