浏览代码

[5.0.x] Fixed #35056 -- Fixed system check crash on reverse m2m relations with related_name in ModelAdmin.filter_horizontal/vertical.

Thanks Thomas Feldmann for the report.

Regression in 107865780aa44914e21d27fdf4ca269bc61c7f01.
Backport of 751d732a3815a68bdb5b7aceda0e7d5981362c4a from main
Mariusz Felisiak 1 年之前
父节点
当前提交
9a182f3d95
共有 3 个文件被更改,包括 41 次插入1 次删除
  1. 1 1
      django/contrib/admin/checks.py
  2. 4 0
      docs/releases/5.0.1.txt
  3. 36 0
      tests/modeladmin/test_checks.py

+ 1 - 1
django/contrib/admin/checks.py

@@ -532,7 +532,7 @@ class BaseModelAdminChecks:
                 field=field_name, option=label, obj=obj, id="admin.E019"
             )
         else:
-            if not field.many_to_many:
+            if not field.many_to_many or isinstance(field, models.ManyToManyRel):
                 return must_be(
                     "a many-to-many field", option=label, obj=obj, id="admin.E020"
                 )

+ 4 - 0
docs/releases/5.0.1.txt

@@ -32,3 +32,7 @@ Bugfixes
 
 * Fixed a regression in Django 5.0 where querysets referenced incorrect field
   names from ``FilteredRelation()`` (:ticket:`35050`).
+
+* Fixed a regression in Django 5.0 that caused a system check crash when
+  ``ModelAdmin.filter_horizontal`` or ``filter_vertical`` contained a reverse
+  many-to-many relation with ``related_name`` (:ticket:`35056`).

+ 36 - 0
tests/modeladmin/test_checks.py

@@ -322,6 +322,24 @@ class FilterVerticalCheckTests(CheckTestCase):
             "admin.E020",
         )
 
+    @isolate_apps("modeladmin")
+    def test_invalid_reverse_m2m_field_with_related_name(self):
+        class Contact(Model):
+            pass
+
+        class Customer(Model):
+            contacts = ManyToManyField("Contact", related_name="customers")
+
+        class TestModelAdmin(ModelAdmin):
+            filter_vertical = ["customers"]
+
+        self.assertIsInvalid(
+            TestModelAdmin,
+            Contact,
+            "The value of 'filter_vertical[0]' must be a many-to-many field.",
+            "admin.E020",
+        )
+
     @isolate_apps("modeladmin")
     def test_invalid_m2m_field_with_through(self):
         class Artist(Model):
@@ -384,6 +402,24 @@ class FilterHorizontalCheckTests(CheckTestCase):
             "admin.E020",
         )
 
+    @isolate_apps("modeladmin")
+    def test_invalid_reverse_m2m_field_with_related_name(self):
+        class Contact(Model):
+            pass
+
+        class Customer(Model):
+            contacts = ManyToManyField("Contact", related_name="customers")
+
+        class TestModelAdmin(ModelAdmin):
+            filter_horizontal = ["customers"]
+
+        self.assertIsInvalid(
+            TestModelAdmin,
+            Contact,
+            "The value of 'filter_horizontal[0]' must be a many-to-many field.",
+            "admin.E020",
+        )
+
     @isolate_apps("modeladmin")
     def test_invalid_m2m_field_with_through(self):
         class Artist(Model):