Login

Add special field lookups to the Admin list_filter display

Author:
whiteinge
Posted:
February 4, 2008
Language:
JavaScript
Version:
Not specified
Score:
3 (after 3 ratings)

Ever wanted to add an atypical field lookup to the Django Admin list_filter filters, like __isnull or __in? This jQuery snippet allows you to do just that.

Since you can access those additional filters by directly typing them into in the Admin URL, the tricky part is to add those to the regular list_filter display. A lot of this code is spent checking on querystring matches which is ugly and error-prone -- if you see any problems or room for improvement, drop me a comment!

A suggestion of where to place this code is in templates/admin/yourapp/yourmodel/change_list.html. Mine kinda looks like this:

{% extends "admin/change_list.html" %}

{% block content %}
<script src="/static/js/jquery-1.2.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
    // the JavaScript posted in this snippet
</script>
{{ block.super }}
{% endblock %}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
$(document).ready(function() {
    function customFilter(heading, filter, text) {
        var filtergroup = $('#changelist-filter h3:contains("'+ heading +'")').next('ul');
        qs = window.location.search;

        // if we're already filtering by a sibling (that isn't "All")
        if (filtergroup.children('li:first').siblings().is('.selected')) {
            // remove sibling querystring from custom filter querystring
            var filterBase = filter.substr(0, filter.indexOf('_'));
            var siblingQs = qs.substr(qs.indexOf(filterBase), qs.indexOf('&', qs.indexOf(filterBase)));
            if (!siblingQs) {
                siblingQs = qs.slice(qs.indexOf(filterBase), qs.length);
            }
            qs = qs.replace(siblingQs, '');
            qs = qs + '&' + filter;
        } else {
            // no current filters, make new
            if (!qs || qs == '?') {
                qs = '?' + filter;
            // already filtering by custom filter, ignore
            } else if (qs.match(filter)) {
                qs = qs;
            // current filters, append
            } else {
                qs = qs + '&' + filter;
            }
        }

        filtergroup.append('<li><a href="'+ qs +'">'+ text +'</a></li>');

        var currentfilter = filtergroup.children('li:last');
        if (window.location.search.match(filter)) {
            currentfilter.addClass('selected');
            currentfilter.siblings().each(function(){
                $(this).removeClass('selected');
                $(this).children('a').attr('href', function() {
                    return this.href.replace(filter, '');
                });
            });
        }
    }

    // Usage examples. Takes three arguments.
    // 1. the exact text above your list_display section
    // 2. the custom field lookup (careful with weird characters here)
    // 3. the text you want the new filter to show up as
    customFilter('By affiliation', 'school__in=A,B', 'School A or B');
    customFilter('By affiliation', 'school__isnull=True', 'No school');
});

More like this

  1. Django Collapsed Stacked Inlines by applecat 1 year, 10 months ago
  2. Django Collapsed Stacked Inlines by mkarajohn 3 years, 11 months ago
  3. Dynamically adding forms to a formset. OOP version. by halfnibble 9 years, 7 months ago
  4. Convert multiple select for m2m to multiple checkboxes in django admin form by abidibo 11 years, 8 months ago
  5. Django admin inline ordering - javascript only implementation by ojhilt 12 years ago

Comments

Dinnerdog (on January 13, 2010):

In your example you have set 'By affiliation' as the heading. How do you get this to appear above yout list_display section?

For example I want to use 'By LEA' but when I set this as the heading nothing appears in the filters. However if I set the heading to an already existing heading then my options appear.

Thanks

#

Please login first before commenting.