diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
a
|
b
|
|
195 | 195 | |
196 | 196 | # Special case -- foo__id__exact and foo__id queries are implied |
197 | 197 | # if foo has been specificially included in the lookup list; so |
198 | | # drop __id if it is the last part. |
199 | | if len(parts) > 1 and parts[-1] == self.model._meta.pk.name: |
| 198 | # drop __id if it is the last part. However, first we need to find |
| 199 | # the pk attribute name. |
| 200 | model = self.model |
| 201 | pk_attr_name = None |
| 202 | for part in parts[:-1]: |
| 203 | field, _, _, _ = model._meta.get_field_by_name(part) |
| 204 | if hasattr(field, 'rel'): |
| 205 | model = field.rel.to |
| 206 | pk_attr_name = model._meta.pk.name |
| 207 | elif isinstance(field, RelatedObject): |
| 208 | model = field.model |
| 209 | pk_attr_name = model._meta.pk.name |
| 210 | else: |
| 211 | pk_attr_name = None |
| 212 | if pk_attr_name and len(parts) > 1 and parts[-1] == pk_attr_name: |
200 | 213 | parts.pop() |
201 | 214 | |
202 | 215 | try: |
diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
a
|
b
|
|
588 | 588 | class AlbumAdmin(admin.ModelAdmin): |
589 | 589 | list_filter = ['title'] |
590 | 590 | |
| 591 | class Employee(Person): |
| 592 | code = models.CharField(max_length=20) |
| 593 | |
| 594 | class WorkHour(models.Model): |
| 595 | datum = models.DateField() |
| 596 | employee = models.ForeignKey(Employee) |
| 597 | |
| 598 | class WorkHourAdmin(admin.ModelAdmin): |
| 599 | list_display = ('datum', 'employee') |
| 600 | list_filter = ('employee',) |
| 601 | |
591 | 602 | admin.site.register(Article, ArticleAdmin) |
592 | 603 | admin.site.register(CustomArticle, CustomArticleAdmin) |
593 | 604 | admin.site.register(Section, save_as=True, inlines=[ArticleInline]) |
… |
… |
|
619 | 630 | admin.site.register(PlotDetails) |
620 | 631 | admin.site.register(CyclicOne) |
621 | 632 | admin.site.register(CyclicTwo) |
| 633 | admin.site.register(WorkHour, WorkHourAdmin) |
622 | 634 | |
623 | 635 | # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. |
624 | 636 | # That way we cover all four cases: |
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
a
|
b
|
|
28 | 28 | FooAccount, Gallery, ModelWithStringPrimaryKey, \ |
29 | 29 | Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast, \ |
30 | 30 | Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit, \ |
31 | | Category, Post, Plot, FunkyTag |
| 31 | Category, Post, Plot, FunkyTag, WorkHour, Employee |
32 | 32 | |
33 | 33 | |
34 | 34 | class AdminViewBasicTest(TestCase): |
… |
… |
|
311 | 311 | except SuspiciousOperation: |
312 | 312 | self.fail("Filters should be allowed if they involve a local field without the need to whitelist them in list_filter or date_hierarchy.") |
313 | 313 | |
| 314 | e1 = Employee.objects.create(name='Anonymous', gender=1, age=22, alive=True, code='123') |
| 315 | e2 = Employee.objects.create(name='Visitor', gender=2, age=19, alive=True, code='124') |
| 316 | WorkHour.objects.create(datum=datetime.datetime.now(), employee=e1) |
| 317 | WorkHour.objects.create(datum=datetime.datetime.now(), employee=e2) |
| 318 | response = self.client.get("/test_admin/admin/admin_views/workhour/") |
| 319 | self.assertEqual(response.status_code, 200) |
| 320 | self.assertContains(response, 'employee__person_ptr__exact') |
| 321 | response = self.client.get("/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=%d" % e1.pk) |
| 322 | self.assertEqual(response.status_code, 200) |
| 323 | |
314 | 324 | class SaveAsTests(TestCase): |
315 | 325 | fixtures = ['admin-views-users.xml','admin-views-person.xml'] |
316 | 326 | |