Fixed #32975 -- Fixed admin system check for inlines with foreign keys to proxy models.

This commit is contained in:
taulant 2021-08-30 17:44:22 +01:00 committed by Mariusz Felisiak
parent b8824e8d17
commit 0e8be73812
2 changed files with 44 additions and 5 deletions

View File

@ -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:

View File

@ -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):