Ticket #17972: 17972.listfilter-fk-with-tofield.diff

File 17972.listfilter-fk-with-tofield.diff, 7.2 KB (added by Julien Phalip, 12 years ago)
  • django/contrib/admin/filters.py

    diff --git a/django/contrib/admin/filters.py b/django/contrib/admin/filters.py
    index b64445e..76b8d30 100644
    a b class FieldListFilter(ListFilter):  
    155155class RelatedFieldListFilter(FieldListFilter):
    156156    def __init__(self, field, request, params, model, model_admin, field_path):
    157157        other_model = get_model_from_relation(field)
    158         rel_name = other_model._meta.pk.name
     158        if hasattr(field, 'rel'):
     159            rel_name = field.rel.get_related_field().name
     160        else:
     161            rel_name = other_model._meta.pk.name
    159162        self.lookup_kwarg = '%s__%s__exact' % (field_path, rel_name)
    160163        self.lookup_kwarg_isnull = '%s__isnull' % field_path
    161164        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 73c2958..2071792 100644
    a b class BaseModelAdmin(object):  
    245245        # if foo has been specificially included in the lookup list; so
    246246        # drop __id if it is the last part. However, first we need to find
    247247        # the pk attribute name.
    248         pk_attr_name = None
     248        rel_name = None
    249249        for part in parts[:-1]:
    250250            try:
    251251                field, _, _, _ = model._meta.get_field_by_name(part)
    class BaseModelAdmin(object):  
    255255                return True
    256256            if hasattr(field, 'rel'):
    257257                model = field.rel.to
    258                 pk_attr_name = model._meta.pk.name
     258                rel_name = field.rel.get_related_field().name
    259259            elif isinstance(field, RelatedObject):
    260260                model = field.model
    261                 pk_attr_name = model._meta.pk.name
     261                rel_name = model._meta.pk.name
    262262            else:
    263                 pk_attr_name = None
    264         if pk_attr_name and len(parts) > 1 and parts[-1] == pk_attr_name:
     263                rel_name = None
     264        if rel_name and len(parts) > 1 and parts[-1] == rel_name:
    265265            parts.pop()
    266266
    267267        if len(parts) == 1:
  • tests/regressiontests/admin_filters/models.py

    diff --git a/tests/regressiontests/admin_filters/models.py b/tests/regressiontests/admin_filters/models.py
    index 2fa6e66..deb8ee8 100644
    a b class Book(models.Model):  
    1313
    1414    def __unicode__(self):
    1515        return self.title
     16
     17
     18class Department(models.Model):
     19    code = models.CharField(max_length=4, unique=True)
     20    description = models.CharField(max_length=50, blank=True, null=True)
     21
     22    def __unicode__(self):
     23        return self.description
     24
     25class Employee(models.Model):
     26    department = models.ForeignKey(Department, to_field="code")
     27    name = models.CharField(max_length=100)
     28
     29    def __unicode__(self):
     30        return self.name
     31 No newline at end of file
  • tests/regressiontests/admin_filters/tests.py

    diff --git a/tests/regressiontests/admin_filters/tests.py b/tests/regressiontests/admin_filters/tests.py
    index b42dfd7..d87c447 100644
    a b import datetime  
    44
    55from django.contrib.admin import (site, ModelAdmin, SimpleListFilter,
    66    BooleanFieldListFilter)
    7 from django.contrib.admin.options import IncorrectLookupParameters
    87from django.contrib.admin.views.main import ChangeList
    98from django.contrib.auth.admin import UserAdmin
    109from django.contrib.auth.models import User
    from django.test import TestCase, RequestFactory  
    1312from django.test.utils import override_settings
    1413from django.utils.encoding import force_unicode
    1514
    16 from .models import Book
     15from .models import Book, Department, Employee
    1716
    1817
    1918def select_by(dictlist, key, value):
    class DecadeFilterBookAdminParameterEndsWith__In(ModelAdmin):  
    113112class DecadeFilterBookAdminParameterEndsWith__Isnull(ModelAdmin):
    114113    list_filter = (DecadeListFilterParameterEndsWith__Isnull,)
    115114
     115class EmployeeAdmin(ModelAdmin):
     116    list_display = ['name', 'department']
     117    list_filter = ['department']
    116118
    117119
    118120class ListFiltersTests(TestCase):
    class ListFiltersTests(TestCase):  
    633635        choices = list(filterspec.choices(changelist))
    634636        self.assertEqual(choices[2]['display'], u'the 1990\'s')
    635637        self.assertEqual(choices[2]['selected'], True)
    636         self.assertEqual(choices[2]['query_string'], '?decade__isnull=the+90s')
    637  No newline at end of file
     638        self.assertEqual(choices[2]['query_string'], '?decade__isnull=the+90s')
     639
     640    def test_fk_with_to_field(self):
     641        """
     642        Ensure that a filter on a FK respects the FK's to_field attribute.
     643        Refs #17972.
     644        """
     645        modeladmin = EmployeeAdmin(Employee, site)
     646
     647        dev = Department.objects.create(code='DEV', description='Development')
     648        design = Department.objects.create(code='DSN', description='Design')
     649        john = Employee.objects.create(name='John Blue', department=dev)
     650        jack = Employee.objects.create(name='Jack Red', department=design)
     651
     652        request = self.request_factory.get('/', {})
     653        changelist = self.get_changelist(request, Employee, modeladmin)
     654
     655        # Make sure the correct queryset is returned
     656        queryset = changelist.get_query_set(request)
     657        self.assertEqual(list(queryset), [john, jack])
     658
     659        filterspec = changelist.get_filters(request)[0][-1]
     660        self.assertEqual(force_unicode(filterspec.title), u'department')
     661        choices = list(filterspec.choices(changelist))
     662
     663        self.assertEqual(choices[0]['display'], u'All')
     664        self.assertEqual(choices[0]['selected'], True)
     665        self.assertEqual(choices[0]['query_string'], '?')
     666
     667        self.assertEqual(choices[1]['display'], u'Development')
     668        self.assertEqual(choices[1]['selected'], False)
     669        self.assertEqual(choices[1]['query_string'], '?department__code__exact=DEV')
     670
     671        self.assertEqual(choices[2]['display'], u'Design')
     672        self.assertEqual(choices[2]['selected'], False)
     673        self.assertEqual(choices[2]['query_string'], '?department__code__exact=DSN')
     674
     675        # Filter by Department=='Development' --------------------------------
     676
     677        request = self.request_factory.get('/', {'department__code__exact': 'DEV'})
     678        changelist = self.get_changelist(request, Employee, modeladmin)
     679
     680        # Make sure the correct queryset is returned
     681        queryset = changelist.get_query_set(request)
     682        self.assertEqual(list(queryset), [john])
     683
     684        filterspec = changelist.get_filters(request)[0][-1]
     685        self.assertEqual(force_unicode(filterspec.title), u'department')
     686        choices = list(filterspec.choices(changelist))
     687
     688        self.assertEqual(choices[0]['display'], u'All')
     689        self.assertEqual(choices[0]['selected'], False)
     690        self.assertEqual(choices[0]['query_string'], '?')
     691
     692        self.assertEqual(choices[1]['display'], u'Development')
     693        self.assertEqual(choices[1]['selected'], True)
     694        self.assertEqual(choices[1]['query_string'], '?department__code__exact=DEV')
     695
     696        self.assertEqual(choices[2]['display'], u'Design')
     697        self.assertEqual(choices[2]['selected'], False)
     698        self.assertEqual(choices[2]['query_string'], '?department__code__exact=DSN')
Back to Top