Join my Asyncio(Python) course on Udemy 👀

Print object as dict in a Django template

May 26, 2021  ‐ 2 min read

When you need to debug an object or model instance in Django templates spinning up a debugger is probably the most appropriate thing to do. However, debugging with print statements can be just so convenient. Just make sure to not push the print statements to production, it will drive your fellow devs mad.

Printing objects in Python gets you their string representation, you can easily get around that by using .__dict__:

>>> u = User()
>>> u.__dict__
{'_state': <django.db.models.base.ModelState object at 0x7fadd961d820>, 'id': None, 'password': '', 'last_login': None, 'is_superuser': False, 'username': '', 'first_name': '', 'last_name': '', 'email': '', 'is_staff': False, 'is_active': True, 'date_joined': datetime.datetime(2021, 5, 26, 10, 4, 9, 501219, tzinfo=<UTC>)}

In Django templates this trick doesn't work unfortunately. If you try something like the code below you end up with an TemplateSyntaxError saying: Variables and attributes may not begin with underscores: 'object.__dict__'.

{% extends 'layouts/base.html' %}

{% block content %}
{{ object.__dict__ }}
{% endblock content %}

One way around this, for debugging purposes, is with a custom template filter. Lets adjust the above example somewhat, we will load a tag library called debug and add the as_dict template filter to the template:

{% extends 'layouts/base.html' %}
{% load debug %}

{% block content %}
{{ object|as_dict }}
{% endblock content %}

This debug tag library is not yet registered, actually it doesn't even exist yet. In order to register the tag library we will add is as a library to the TEMPLATES settings in settings.py

TEMPLATES = [
    {
        'OPTIONS': {
            ...
            'libraries':{
                'debug': 'project.templatetags.debug',
            }
        },
    },
]

Next we need to create the library we added to the settings, with the path: project/templatetags/debug.py.

In this templatetags library we add the as_dict filter we used before in our template.

from django import template

register = template.Library()


def as_dict(value):
    return value.__dict__


register.filter('as_dict', as_dict)