Access Elements in a Django JSONField List

I set up my Django project to use MySQL, so that I could use a list in a JSONField. Little did I know that accessing elements of that list by their index would be another problem entirely. There are two confounding things. First, in Jinja2, you can access a for-loop index with the loop.index or loop.index0 keywords, but in a Django project, you need to use forloop.counter or forloop.counter0`. The trailing zero on those keywords specify a zero-indexed counter rather than a one-indexed counter. The second thing is that you need to provide a custom template tag in order to cleanly access elements in a JSONField list by their index.

The first item is easy enough: when you’re using Django, use for loop.counter0 instead of the builtin Jinja2 loop.index0. The second item requires more work. First, create a package named templatetags in the same directory in your app as your models.py and views.py; “creating a package” in this sense just means creating a new directory called templatetags, and placing an empty __init__.py file in it. Next, in the templatetags directory, add a file named index.py

from django import template

register = template.Library()

@register.filter
def index(List, i):
    return List[int(i)]

Now, in your template, you can say,

{% load index %}
...
{% for some_other_thing in some_list %}
  {{ model.list_of_items | index:forloop.counter0 }}
{% endfor %}

To get this to work as expected, you’ll have to restart the server if it’s running.