summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaulant <taliraj@outlook.com>2021-08-30 17:44:22 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-09-03 06:48:32 +0200
commit0e8be73812a6e62d5a6b12a585d133b56bc2bf52 (patch)
tree37e31a58d4eca2dd7b82dd5bab998fcfc5a15e67
parentb8824e8d17434957650517370f739e340867c381 (diff)
Fixed #32975 -- Fixed admin system check for inlines with foreign keys to proxy models.
-rw-r--r--django/forms/models.py20
-rw-r--r--tests/modeladmin/test_checks.py29
2 files changed, 44 insertions, 5 deletions
diff --git a/django/forms/models.py b/django/forms/models.py
index a88c384841..16681ba80b 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -1009,9 +1009,17 @@ def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
fks_to_parent = [f for f in opts.fields if f.name == fk_name]
if len(fks_to_parent) == 1:
fk = fks_to_parent[0]
- if not isinstance(fk, ForeignKey) or \
- (fk.remote_field.model != parent_model and
- fk.remote_field.model not in parent_model._meta.get_parent_list()):
+ parent_list = parent_model._meta.get_parent_list()
+ if not isinstance(fk, ForeignKey) or (
+ # ForeignKey to proxy models.
+ fk.remote_field.model._meta.proxy and
+ fk.remote_field.model._meta.proxy_for_model not in parent_list
+ ) or (
+ # ForeignKey to concrete models.
+ not fk.remote_field.model._meta.proxy and
+ fk.remote_field.model != parent_model and
+ fk.remote_field.model not in parent_list
+ ):
raise ValueError(
"fk_name '%s' is not a ForeignKey to '%s'." % (fk_name, parent_model._meta.label)
)
@@ -1021,11 +1029,15 @@ def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
)
else:
# Try to discover what the ForeignKey from model to parent_model is
+ parent_list = parent_model._meta.get_parent_list()
fks_to_parent = [
f for f in opts.fields
if isinstance(f, ForeignKey) and (
f.remote_field.model == parent_model or
- f.remote_field.model in parent_model._meta.get_parent_list()
+ f.remote_field.model in parent_list or (
+ f.remote_field.model._meta.proxy and
+ f.remote_field.model._meta.proxy_for_model in parent_list
+ )
)
]
if len(fks_to_parent) == 1:
diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py
index f224770948..1d6f1ba023 100644
--- a/tests/modeladmin/test_checks.py
+++ b/tests/modeladmin/test_checks.py
@@ -4,7 +4,7 @@ from django.contrib.admin import BooleanFieldListFilter, SimpleListFilter
from django.contrib.admin.options import VERTICAL, ModelAdmin, TabularInline
from django.contrib.admin.sites import AdminSite
from django.core.checks import Error
-from django.db.models import F, Field, Model
+from django.db.models import CASCADE, F, Field, ForeignKey, Model
from django.db.models.functions import Upper
from django.forms.models import BaseModelFormSet
from django.test import SimpleTestCase
@@ -1121,6 +1121,33 @@ class FkNameCheckTests(CheckTestCase):
self.assertIsValid(TestModelAdmin, ValidationTestModel)
+ def test_proxy_model_parent(self):
+ class Parent(Model):
+ pass
+
+ class ProxyChild(Parent):
+ class Meta:
+ proxy = True
+
+ class ProxyProxyChild(ProxyChild):
+ class Meta:
+ proxy = True
+
+ class Related(Model):
+ proxy_child = ForeignKey(ProxyChild, on_delete=CASCADE)
+
+ class InlineFkName(admin.TabularInline):
+ model = Related
+ fk_name = 'proxy_child'
+
+ class InlineNoFkName(admin.TabularInline):
+ model = Related
+
+ class ProxyProxyChildAdminFkName(admin.ModelAdmin):
+ inlines = [InlineFkName, InlineNoFkName]
+
+ self.assertIsValid(ProxyProxyChildAdminFkName, ProxyProxyChild)
+
class ExtraCheckTests(CheckTestCase):