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
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Awesome, works very well and a very good idea, thanks!
#
Nice one, thanks.
#
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.