How to render an arbitrary set of key->value pairs from a JSONField in a Jinja2 template?

I'm trying to add debug information to a frontend; for reasons that don't need to be gone into at the moment I'm storing the pertinent information in a JSONField.

Storing and retrieving the information works correctly, but when I try to render it via J2 to the page it's supposed to be at I'm running into some issues.

Here's the segment in question:

          {% for log in connection.debug_logs.all %}
            <tr>
                <td></td>
                <td>{{ log.log_message }}</td>
                <td>
                    {% for key in log.log_data %}
                      {{ key }}: {{ log.log_data.key }} <br/>
                    {% endfor %}
                </td>
            </tr>
          {% endfor %}

What I'm hoping for is for that to produce a series of lines of key: value. What I'm getting instead is:

                <td>Login requested by vmx1.internal (11.22.33.44)</td>
                <td>
                      Framed-Route:  <br/>
                      Service-Type:  <br/>
                      Framed-IP-Address:  <br/>
                      Framed-IPv6-Route:  <br/>
                      control:Auth-Type:  <br/>
                      Framed-IPv6-Prefix:  <br/>
                      Delegated-IPv6-Prefix:  <br/>
                      ERX-Egress-Policy-Name:  <br/>
                      ERX-Ingress-Policy-Name:  <br/>
                      ERX-Virtual-Router-Name:  <br/>
                      control:Cleartext-Password:  <br/>
                </td>

Using {{ log.log_data | pprint }} does yield the keys and values, but renders them as a plaintext JSON string which gets flattened by the html renderer and isn't terribly useful for debugging purposes.

Trying 'log.log_data[key]' instead yields a 'Could not parse the remainder' error.

I've tried the suggestions in this question as well as these and a few others that came up during google searches, but none of them seem to address this issue -- all of them are either working with known keys, working with an actual dict instead of a JSONField, or sometimes both.

I'm probably missing something very simple and straightforward, but I've run out of ways to phrase my question in a search engine. Any tips?

Do the conversion from json inside your view to have a greater range of utilities than inside the jinja2 template world.

import json
DEBUG_LOGS_JSON = "[
    {"log_data": {"Framed-Route": "route1", "Service-Type": "type1"}, "log_message": "my"},
    {"log_data": {"Framed-Route": "route2", "Service-Type": "type2"}, "log_message": "name"},
    {"log_data": {"Framed-Route": "route3", "Service-Type": "type3"}, "log_message": "Tarquinius"},
]"

def my_view(request):
    my_dict = json.loads(DEBUG_LOGS_JSON)  # instead you could also restructure the data passed to the template here.
    return render("my_template.html", context=my_dict)
{% for dictionary in my_dict %}
<tr>
  <td>{{ dictionary.log_message }}</td>
  <td>
    {% for key, value in dictionary.log_data.items() %}
    {{ key }}: {{ value }} <br/>
    {% endfor %}
  </td>
</tr>
{% endfor %}

If this does not represent the structure of your json, then please provide an example. Let me know how it goes.

After a lot of hair-tearing, I discovered that Django templates are not quite exactly the same as Jinja2 templates.

Specifically, what the J2 documentation told me to write as

{% for key, value in log.log_data.items() %}

should instead have been

{% for key, value in log.log_data.items %}

This worked and got me the output I was looking for. I'm leaving this as an answer here in case someone else runs into the same issue.

Back to Top