#-*- coding: utf-8 -*-
#!/usr/bin/env python
from django.db import models
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext as _
class FkFilterSpec(ChoicesFilterSpec):
def __init__(self, f, request, params, model, model_admin):
super(FkFilterSpec, self).__init__(f, request, params, model, model_admin)
# ******* Extract parameters ********
the_args = f.fk_filterspec.copy()
#The field of the related table
fk_field = the_args['fk_field']
#The name in the related table to use as label in the choices
label = the_args.pop('label', '')
#a title: by default the lookup arg
self.filter_title = the_args.pop('title', '')
#the foreign key field. By default the field the filter is assigned
fk = the_args.pop('fk', f.name)
# ******* Build the filter definition ********
self.lookup_kwarg = '{0}__{1}'.format(fk, fk_field)
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.lookup_labels = {}
#get the list of values
values_list = model.objects.values_list(self.lookup_kwarg, flat=True)
#get the
if label:
label_field = '{0}__{1}__{2}'.format(fk, fk_field, label)
else:
label_field = '{0}__{1}'.format(fk, fk_field)
labels = model.objects.values_list(label_field, flat=True)
for (v, l) in zip(values_list, labels):
self.lookup_labels[v] = l
self.lookup_choices = self.lookup_labels.keys()
def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}
for val in self.lookup_choices:
yield {'selected': smart_unicode(val) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: val}),
'display': smart_unicode(self.lookup_labels[val])}
def title(self):
if self.filter_title:
return self.filter_title
else:
return super(FkFilterSpec, self).title()
@classmethod
def register_filterspec(cls):
"""register the filter. To be called in the models.py"""
FilterSpec.filter_specs.insert(0,
(lambda f: len(getattr(f, 'fk_filterspec', [])), cls)
)
### In the models.py
from filterspecs import FkFilterSpec
FkFilterSpec.register_filterspec()
class Country(models.Model):
name = models.CharField(max_length=100)
class City(models.Model):
name = models.CharField(max_length=100)
country = models.ForeignKey(Country)
class Company(models.Model):
name = models.CharField(max_length=100)
city = models.ForeignKey(City)
city.fk_filterspec = {'fk_field':'country',
'label':'name',
'title':'Country'}
Comments
I had to change the
__init__()method to make it work with Django 1.3It was giving errors because an unexpected
field_pathkeyword argument.#
@gmandx
Thanks for your help! I had the same problem and this solved it.
#