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)