【问题标题】:HTMX parsing JSON response issueHTMX 解析 JSON 响应问题
【发布时间】:2022-01-24 14:32:43
【问题描述】:

我有一个将一些数据发布到 Django 后端并返回 JSON 响应的页面。我在使用模板解析它时遇到问题。 任何帮助,将不胜感激。提前谢谢你。

    <div class="card-body">
            <form>
            {% csrf_token %}
                <div class="input-group mb-3">
                    <label class="input-group-text">Command</label>
                    <select class="form-select" name="run_show_command" id="run_show_command">
                        <option selected disabled>Choose...</option>
                        <option value="{{ data.version.id }}:1">show ip interface brief</option>
                        <option value="{{ data.version.id }}:2">show interfaces description</option>
                        <option value="{{ data.version.id }}:3">show ip arp</option>
                        <option value="{{ data.version.id }}:4">show ip route</option>
                        <option value="{{ data.version.id }}:5">show ip cef</option>
                        <option value="{{ data.version.id }}:6">show version</option>
                    </select>
                    <button type="submit" class="btn btn-sm btn-success" hx-post="{% url 'inventory:device_run_command' %}" hx-target="#command_output" mustache-template="m_template" hx-indicator="#loader_bars">
                        <i class="fas fa-terminal"></i> Run
                    </button>
                </div>
            </form>
            <div class="d-flex justify-content-center" hx-ext="client-side-templates" id="command_output">
                <img id="loader_bars" class="htmx-indicator" alt="Loading..." src="{% static 'images/loaders/bars.svg' %}"/>
                <template id="m_template" type="text/mustache">
                    {% for data in dataset %}
                    {% for key, value in data.items %}
                        <li>{{ key }} {{ value }}</li>
                    {% endfor %}
                    {% endfor %}
                </template>
            </div>
        </div>

JSON:

 [{ "intf": "GigabitEthernet1", "ipaddr": "10.10.20.48", "status": "up", "proto": "up" }, { "intf": "GigabitEthernet2", "ipaddr": "unassigned", "status": "administratively down", "proto": "down" }, { "intf": "GigabitEthernet3", "ipaddr": "unassigned", "status": "administratively down", "proto": "down" }, { "intf": "Loopback1", "ipaddr": "10.10.10.100", "status": "up", "proto": "up" }, { "intf": "Loopback123", "ipaddr": "unassigned", "status": "up", "proto": "up" }, { "intf": "Loopback510", "ipaddr": "50.10.10.10", "status": "up", "proto": "up" }, { "intf": "Loopback511", "ipaddr": "51.10.10.10", "status": "up", "proto": "up" }, { "intf": "Loopback512", "ipaddr": "52.10.10.10", "status": "up", "proto": "up" }, { "intf": "Loopback666", "ipaddr": "6.6.6.6", "status": "up", "proto": "up" } ]

【问题讨论】:

  • 具体是什么不起作用?你有错误吗?
  • 不,我希望根据模板解析输出,但它是原始渲染的(如 JSON 示例中所示)。
  • 仅查看 HTMX 文档中的示例,我认为您需要在 HTML 中将hx-ext="client-side-templates" 向上移动,例如在&lt;div class="card-body"&gt; 元素上。
  • 我会试一试,但到目前为止我已经尝试了所有方法,但没有任何效果,将再试一次:)
  • 好的,所以我把它移到了上面的 DIV(卡和卡体),然后根本没有显示输出:/

标签: django htmx


【解决方案1】:

您不能像在 &lt;template&gt; 标记中尝试的那样在前端使用 Django 模板。 HTMX 支持 3 个 javascript 模板库:mustache.jshandlebarsnunjucks。最接近 Django 的是 nunjucks,它的灵感来自 Jinja2,它的灵感来自 Django Templates,所以或多或少会比较熟悉。

首先,不要忘记将 HTMX 扩展和 nunjucks 库添加到您的 JS 包中,或者直接添加到 HTML 基础模板中,例如:

<script src="https://unpkg.com/htmx.org@1.6.1"></script>
<script src="https://unpkg.com/htmx.org@1.6.1/dist/ext/client-side-templates.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nunjucks/3.0.1/nunjucks.min.js"
   integrity="sha512-IIuR+Zp8wvP0dxNcSsRPoL7SXzP1kGmosDtcU7f6cPObZ9F5Ze/icFSRH/SqigP468jGwDm2XOE0/gSGm/cTBw=="
   crossorigin="anonymous" referrerpolicy="no-referrer"></script>

更新的模板:

<div class="card-body">
  <form>
    {% csrf_token %}
    <div class="input-group mb-3" hx-ext="client-side-templates">
      <label class="input-group-text">Command</label>
      <select class="form-select" name="run_show_command" id="run_show_command">
        <option selected disabled>Choose...</option>
        <option value="{{ data.version.id }}:1">show ip interface brief</option>
        <option value="{{ data.version.id }}:2">show interfaces description</option>
        <option value="{{ data.version.id }}:3">show ip arp</option>
        <option value="{{ data.version.id }}:4">show ip route</option>
        <option value="{{ data.version.id }}:5">show ip cef</option>
        <option value="{{ data.version.id }}:6">show version</option>
      </select>
      <button type="submit" class="btn btn-sm btn-success" hx-post="{% url 'inventory:device_run_command' %}"
        hx-target="#command_output" nunjucks-template="m_template" hx-indicator="#loader_bars">
        <i class="fas fa-terminal"></i> Run
      </button>
    </div>
  </form>
  <div class="d-flex justify-content-center">
    <div id="command_output">
      <img id="loader_bars" class="htmx-indicator" alt="Loading..." src="{% static 'images/loaders/bars.svg' %}" />
    </div>
    <template id="m_template">
    {% verbatim %}
      <ul>
        {% for item in items %}
        {% for key, value in item %}
        <li>{{ key }} {{ value }}</li>
        {% endfor %}
        {% endfor %}
      </ul>
    {% endverbatim %}
    </template>
  </div>
</div>

请注意,我将hx-ext 属性移动到按钮的父 div 中,否则它将不起作用。 Nunjucks 有很多 similar syntax,但是例如,我们不需要在嵌套循环中附加 .items

编辑:我之前错过了一个非常重要的细节:由于 nunjucks 和 DTL 的语法非常相似,我们必须将 nunjucks 模板嵌入到 {% verbatim %} 块中,告诉 Django 忽略它。否则它会在后端由 Django 评估,而不是由前端的 nunjucks 评估。

此外,您需要在 JSON 文件中有一个顶级键,这将是第一个 for 循环中的键。

{
    "items": [
        {
            "intf": "GigabitEthernet1",
            "ipaddr": "10.10.20.48",
            "status": "up",
            "proto": "up"
        },
        {
            "intf": "GigabitEthernet2",
            "ipaddr": "unassigned",
            "status": "administratively down",
            "proto": "down"
        },
    ]
}

【讨论】:

  • 还是不行。也刚刚发现:dev.to/marcusatlocalhost/handle-json-api-results-in-htmx-f46 所以在使用 nunjucks 时,不使用
  • 好吧,你可能有不同的问题,或者错误地执行了我的建议。我创建了一个jsFiddle playground,您可以在其中看到我的建议是正确的,并产生您想要的结果。提到的 nunjucks 方法只是一个例子。如果您查看 HTMX 扩展的 source code,您会发现 HTMX 可以从任何地方提取模板代码,然后它会调用相应的 nunjucks 渲染方法,因此它也可以与 &lt;template&gt; 一起使用。
  • 我已经按照您的建议复制了它,您可以看看:github.com/sngx13/net_autom8/blob/master/templates/inventory/… 在 Chrome 调试中可以正确看到返回的 JSON 数据,但页面上没有显示任何内容。如果我“破坏”模板,例如 nunjucks-template="#cmd_output_template" (注意哈希)。输出未格式化,但我在控制台中得到以下信息:DOMException:无法在“文档”上执行“querySelector”:“##cmd_output_template”不是有效的选择器。所以这表明模板有问题?
  • 您确定返回正确的 JSON 数据吗?我认为您在cli_command_runner 中有一个缩进错误。您更新了platform 变量,但随后您必须回到主功能块级别。
  • 否则你的模板修改是正确的,我只是在本地测试了它(将hx-post替换为hx-get="local.json"),它工作正常,按预期呈现列表。
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-14
相关资源
最近更新 更多