Ticket #17972: 17972.listfilter-fk-with-tofield.1-3-X.diff

File 17972.listfilter-fk-with-tofield.1-3-X.diff, 7.1 KB (added by Julien Phalip, 12 years ago)

Same patch for the 1.3.X branch

  • django/contrib/admin/filterspecs.py

    diff -r a6d8d77ea99e django/contrib/admin/filterspecs.py
    a b  
    7474            self.lookup_title = other_model._meta.verbose_name
    7575        else:
    7676            self.lookup_title = f.verbose_name # use field name
    77         rel_name = other_model._meta.pk.name
     77        if hasattr(f, 'rel'):
     78            rel_name = f.rel.get_related_field().name
     79        else:
     80            rel_name = other_model._meta.pk.name
    7881        self.lookup_kwarg = '%s__%s__exact' % (self.field_path, rel_name)
    79         self.lookup_kwarg_isnull = '%s__isnull' % (self.field_path)
     82        self.lookup_kwarg_isnull = '%s__isnull' % self.field_path
    8083        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
    8184        self.lookup_val_isnull = request.GET.get(
    8285                                      self.lookup_kwarg_isnull, None)
     
    176179
    177180class DateFieldFilterSpec(FilterSpec):
    178181    def __init__(self, f, request, params, model, model_admin,
    179                  field_path=None): 
     182                 field_path=None):
    180183        super(DateFieldFilterSpec, self).__init__(f, request, params, model,
    181184                                                  model_admin,
    182185                                                  field_path=field_path)
  • django/contrib/admin/options.py

    diff -r a6d8d77ea99e django/contrib/admin/options.py
    a b  
    225225        # if foo has been specificially included in the lookup list; so
    226226        # drop __id if it is the last part. However, first we need to find
    227227        # the pk attribute name.
    228         pk_attr_name = None
     228        rel_name = None
    229229        for part in parts[:-1]:
    230230            field, _, _, _ = model._meta.get_field_by_name(part)
    231231            if hasattr(field, 'rel'):
    232232                model = field.rel.to
    233                 pk_attr_name = model._meta.pk.name
     233                rel_name = field.rel.get_related_field().name
    234234            elif isinstance(field, RelatedObject):
    235235                model = field.model
    236                 pk_attr_name = model._meta.pk.name
     236                rel_name = model._meta.pk.name
    237237            else:
    238                 pk_attr_name = None
    239         if pk_attr_name and len(parts) > 1 and parts[-1] == pk_attr_name:
     238                rel_name = None
     239        if rel_name and len(parts) > 1 and parts[-1] == rel_name:
    240240            parts.pop()
    241241
    242242        try:
  • tests/regressiontests/admin_filterspecs/models.py

    diff -r a6d8d77ea99e tests/regressiontests/admin_filterspecs/models.py
    a b  
    2121        default=NO,
    2222        choices=YES_NO_CHOICES
    2323    )
     24
     25
     26class Department(models.Model):
     27    code = models.CharField(max_length=4, unique=True)
     28    description = models.CharField(max_length=50, blank=True, null=True)
     29
     30    def __unicode__(self):
     31        return self.description
     32
     33class Employee(models.Model):
     34    department = models.ForeignKey(Department, to_field="code")
     35    name = models.CharField(max_length=100)
     36
     37    def __unicode__(self):
     38        return self.name
     39
     40    class Meta:
     41        ordering = ['id']
     42 No newline at end of file
  • tests/regressiontests/admin_filterspecs/tests.py

    diff -r a6d8d77ea99e tests/regressiontests/admin_filterspecs/tests.py
    a b  
    66from django.contrib.admin.views.main import ChangeList
    77from django.utils.encoding import force_unicode
    88
    9 from models import Book, BoolTest
     9from models import Book, BoolTest, Employee, Department
    1010
    1111def select_by(dictlist, key, value):
    1212    return [x for x in dictlist if x[key] == value][0]
     
    200200        self.assertEqual(choice['selected'], True)
    201201        self.assertEqual(choice['query_string'], '?completed__exact=1')
    202202
     203    def test_fk_with_to_field(self):
     204        """
     205        Ensure that a filter on a FK respects the FK's to_field attribute.
     206        Refs #17972.
     207        """
     208        modeladmin = EmployeeAdmin(Employee, admin.site)
     209
     210        dev = Department.objects.create(code='DEV', description='Development')
     211        design = Department.objects.create(code='DSN', description='Design')
     212        john = Employee.objects.create(name='John Blue', department=dev)
     213        jack = Employee.objects.create(name='Jack Red', department=design)
     214
     215        request = self.request_factory.get('/', {})
     216        changelist = self.get_changelist(request, Employee, modeladmin)
     217
     218        # Make sure the correct queryset is returned
     219        queryset = changelist.get_query_set()
     220        self.assertEqual(list(queryset), [john, jack])
     221
     222        filterspec = changelist.get_filters(request)[0][-1]
     223        self.assertEqual(force_unicode(filterspec.title()), u'department')
     224        choices = list(filterspec.choices(changelist))
     225
     226        self.assertEqual(choices[0]['display'], u'All')
     227        self.assertEqual(choices[0]['selected'], True)
     228        self.assertEqual(choices[0]['query_string'], '?')
     229
     230        self.assertEqual(choices[1]['display'], u'Development')
     231        self.assertEqual(choices[1]['selected'], False)
     232        self.assertEqual(choices[1]['query_string'], '?department__code__exact=DEV')
     233
     234        self.assertEqual(choices[2]['display'], u'Design')
     235        self.assertEqual(choices[2]['selected'], False)
     236        self.assertEqual(choices[2]['query_string'], '?department__code__exact=DSN')
     237
     238        # Filter by Department=='Development' --------------------------------
     239
     240        request = self.request_factory.get('/', {'department__code__exact': 'DEV'})
     241        changelist = self.get_changelist(request, Employee, modeladmin)
     242
     243        # Make sure the correct queryset is returned
     244        queryset = changelist.get_query_set()
     245        self.assertEqual(list(queryset), [john])
     246
     247        filterspec = changelist.get_filters(request)[0][-1]
     248        self.assertEqual(force_unicode(filterspec.title()), u'department')
     249        choices = list(filterspec.choices(changelist))
     250
     251        self.assertEqual(choices[0]['display'], u'All')
     252        self.assertEqual(choices[0]['selected'], False)
     253        self.assertEqual(choices[0]['query_string'], '?')
     254
     255        self.assertEqual(choices[1]['display'], u'Development')
     256        self.assertEqual(choices[1]['selected'], True)
     257        self.assertEqual(choices[1]['query_string'], '?department__code__exact=DEV')
     258
     259        self.assertEqual(choices[2]['display'], u'Design')
     260        self.assertEqual(choices[2]['selected'], False)
     261        self.assertEqual(choices[2]['query_string'], '?department__code__exact=DSN')
     262
     263
    203264class CustomUserAdmin(UserAdmin):
    204265    list_filter = ('books_authored', 'books_contributed')
    205266
     
    209270
    210271class BoolTestAdmin(admin.ModelAdmin):
    211272    list_filter = ('completed',)
     273
     274class EmployeeAdmin(admin.ModelAdmin):
     275    list_display = ['name', 'department']
     276    list_filter = ['department']
     277 No newline at end of file
Back to Top