Login

Filter by taggit tags in the admin

Author:
flupke
Posted:
October 12, 2011
Language:
Python
Version:
1.3
Tags:
filter admin taggit
Score:
4 (after 4 ratings)

A FilterSpec that can be used to filter by taggit tags in the admin.

To use, simply import this module (for example in models.py), and add the name of your TaggableManager field in the list_filter attribute of your ModelAdmin class.

 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
50
from django.db import models
from django.contrib.admin.filterspecs import FilterSpec, RelatedFilterSpec
from django.contrib.admin.util import get_model_from_relation
from django.db.models import Count
from taggit.managers import TaggableManager


class TaggitFilterSpec(RelatedFilterSpec):
    """
    A FilterSpec that can be used to filter by taggit tags in the admin.

    To use, simply import this module (for example in `models.py`), and add the
    name of your :class:`taggit.managers.TaggableManager` field in the
    :attr:`list_filter` attribute of your :class:`django.contrib.ModelAdmin`
    class.
    """

    def __init__(self, f, request, params, model, model_admin,
                 field_path=None):
        super(RelatedFilterSpec, self).__init__(
            f, request, params, model, model_admin, field_path=field_path)

        other_model = get_model_from_relation(f)
        if isinstance(f, (models.ManyToManyField,
                          models.related.RelatedObject)):
            # no direct field on this model, get name from other model
            self.lookup_title = other_model._meta.verbose_name
        else:
            self.lookup_title = f.verbose_name # use field name
        rel_name = other_model._meta.pk.name
        self.lookup_kwarg = '%s__%s__exact' % (self.field_path, rel_name)
        self.lookup_kwarg_isnull = '%s__isnull' % (self.field_path)
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
        self.lookup_val_isnull = request.GET.get(
                                      self.lookup_kwarg_isnull, None)
        # Get tags and their count
        through_opts = f.through._meta
        count_field = ("%s_%s_items" % (through_opts.app_label,
                through_opts.object_name)).lower()
        queryset = getattr(f.model, f.name).all()
        queryset = queryset.annotate(num_times=Count(count_field))
        queryset = queryset.order_by("-num_times")
        self.lookup_choices = [(t.pk, "%s (%s)" % (t.name, t.num_times)) 
                for t in queryset]


# HACK: we insert the filter at the beginning of the list to avoid the manager
# to be associated with a RelatedFilterSpec
FilterSpec.filter_specs.insert(0, (lambda f: isinstance(f, TaggableManager),
    TaggitFilterSpec))

More like this

  1. Filter by taggit tags in the admin (Django 1.4) by albertorcf 2 years, 10 months ago
  2. Changelist filter by ForeignKey by overclocked 4 years, 7 months ago
  3. Hyperlink list filter by lifefloatsby 7 years, 6 months ago
  4. Test Suite URL Coverage by jterrace 3 years, 4 months ago
  5. Filter by first letter inclusion tag by slafs 5 years, 1 month ago

Comments

quinode (on October 12, 2011):

Awesome, works very well and a very good idea, thanks!

#

jasisz (on October 13, 2011):

Nice one, thanks.

#

nathanblack (on August 30, 2012):

Things seem to have changed since 1.3. Under 1.4.1 I'm getting a "No module named filterspecs" exception.

#

Please login first before commenting.