From f80669d2f5a5f1db9e9b73ca893fefba34f955e7 Mon Sep 17 00:00:00 2001 From: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> Date: Wed, 6 Dec 2023 19:03:41 +0100 Subject: [PATCH] Fixed #35020 -- Fixed ModelAdmin.lookup_allowed() for non-autofield primary keys. Thanks Joshua Goodwin for the report. Regression in 45ecd9acca9b36093e274f47b6877a5f79108d9e. --- django/contrib/admin/options.py | 22 +++++++++++----------- docs/releases/5.0.1.txt | 4 +++- tests/modeladmin/tests.py | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index b045b2df025..af69f4cb3b5 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -474,24 +474,24 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass): # Lookups on nonexistent fields are ok, since they're ignored # later. break - if not prev_field or ( - prev_field.is_relation - and field not in model._meta.parents.values() - and field is not model._meta.auto_field - and ( - model._meta.auto_field is None - or part not in getattr(prev_field, "to_fields", []) - ) - ): - relation_parts.append(part) if not getattr(field, "path_infos", None): # This is not a relational field, so further parts # must be transforms. break + if ( + not prev_field + or (field.is_relation and field not in model._meta.parents.values()) + or ( + prev_field.is_relation + and model._meta.auto_field is None + and part not in getattr(prev_field, "to_fields", []) + ) + ): + relation_parts.append(part) prev_field = field model = field.path_infos[-1].to_opts.model - if len(relation_parts) <= 1: + if not relation_parts: # Either a local field filter, or no fields at all. return True valid_lookups = {self.date_hierarchy} diff --git a/docs/releases/5.0.1.txt b/docs/releases/5.0.1.txt index f1b6e0f8bbe..871f55ec6d6 100644 --- a/docs/releases/5.0.1.txt +++ b/docs/releases/5.0.1.txt @@ -9,4 +9,6 @@ Django 5.0.1 fixes several bugs in 5.0. Bugfixes ======== -* ... +* Reallowed, following a regression in Django 5.0, using a foreign key to a + model with a primary key that is not ``AutoField`` in + :attr:`.ModelAdmin.list_filter` (:ticket:`35020`). diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py index ec46b04c2ea..e0c4d6e7271 100644 --- a/tests/modeladmin/tests.py +++ b/tests/modeladmin/tests.py @@ -162,6 +162,20 @@ class ModelAdminTests(TestCase): True, ) + @isolate_apps("modeladmin") + def test_lookup_allowed_non_autofield_primary_key(self): + class Country(models.Model): + id = models.CharField(max_length=2, primary_key=True) + + class Place(models.Model): + country = models.ForeignKey(Country, models.CASCADE) + + class PlaceAdmin(ModelAdmin): + list_filter = ["country"] + + ma = PlaceAdmin(Place, self.site) + self.assertIs(ma.lookup_allowed("country__id__exact", "DE", request), True) + @isolate_apps("modeladmin") def test_lookup_allowed_foreign_primary(self): class Country(models.Model):