[Answered ]-HTMX parsing JSON response issue

1👍

You cannot use Django templates on the frontend like you tried in the <template> tag. HTMX supports 3 javascript templating library: mustache.js, handlebars and nunjucks. The closest one to Django is nunjucks, which is inspired by Jinja2, which is inspired by Django Templates, so it will be more-or-less familiar.

So first, don’t forget to add the HTMX extension and nunjucks library to your JS bundle, or directly into the HTML base template, e.g.:

<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>

The updated template:

<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>

Note that I moved the hx-ext attribute the the button’s parent div, otherwise it won’t work. Nunjucks has quite similar syntax, but for example, we don’t need to append .items in the nested loop.

Edit: I missed a very important detail previously: since nunjucks and DTL has very similar syntax, we have to embed the nunjucks template in a {% verbatim %} block that tells Django to just ignore it. Otherwise it gets evaluated by Django at the backend instead of nunjucks at the frontend.

Furthermore you need to have a top level key in your JSON file, that will be the key in the first for loop.

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

Leave a comment