A few weeks ago Django’s team revealed a data leakage bug in the admin application that affects an extremely interesting and undocumented feature. A user that has access to a change_list
page of an object in the admin interface can filter this list by adding some parameters in the URL. Django will parse them and filter the queryset using the given criteria. Before this security fix you could use this feature out of the box and there was no control over the criteria that were passed by the user. Information outside of an admin user’s permission could leak.
In order to avoid this a new method called lookup_allowed
has been added to the ModelAdmin
. By default this method restricts the lookup to what is declared in list_filter
or date_hierarchy
. As with most things in Django, you can easily override this function in the subclass of ModelAdmin
to allow for additional lookups. For the purpose of this blog post, we’ll leave that as an exercise for the reader, but see this blog post by Chris Adams for more details.
The Basics
Let’s assume we have an app in our project called newsroom that is used to manage published content. A peek into models.py
shows us:
&
between each one:
This is not all you can also do join tables to narrow down your choices:
datetime
is also supported and there is very little suprised in the syntax:
boolean
fields are a bit more tricky because you need to actually pass an integer 0 (False) 1(True)
These are just a few examples, but you can create any number of complex filters by following Django’s documentation on database queries.
Admin integration
Being able to dynamically craft the URLs to build the query is useful but limited to people that are “in the know.” While working on this article, Martin brought to my attention that these links can easily be integrated into the django.contrib.admin
interface by overriding the admin template.
The change_list.html
template has its own block:
{% block filters %}
{% if cl.has_filters %}
{% trans ‘Filter’ %}
{% for spec in cl.filter_specs }{ admin_list_filter cl spec }{ endfor %}
Due to the current structure of the admin templates, you’ll need to maintain some boiler-plate code1. You can minimize that, however, thanks to block.super
.
/admin/newsroom/article/
If you want to use this in a template you can take advantage of the {% url %} tag.
Conclusion
Even though the Django admin does not currently provide a nice UI for adding custom filters, you can still take advantage of this hidden gem. They provide your users with easily bookmarked links to the information they care about. You could also use this technique to create a dashboard or reports page.
1 Ticket #5833 aims to make this process even easier in the future