From c3fdeb28fff35573bf86ef04b234c7f5817b0dea Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Wed, 22 Jan 2014 00:25:33 +0700 Subject: [PATCH] Fixed #21846 -- Made NestedObjects handle related_name with %(app_label)s or %(class)s. --- django/contrib/admin/utils.py | 8 ++++++-- tests/admin_util/models.py | 15 +++++++++++++++ tests/admin_util/tests.py | 12 +++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/django/contrib/admin/utils.py b/django/contrib/admin/utils.py index 4092b67c0e..0b74a6e75f 100644 --- a/django/contrib/admin/utils.py +++ b/django/contrib/admin/utils.py @@ -156,10 +156,14 @@ class NestedObjects(Collector): def add_edge(self, source, target): self.edges.setdefault(source, []).append(target) - def collect(self, objs, source_attr=None, **kwargs): + def collect(self, objs, source=None, source_attr=None, **kwargs): for obj in objs: if source_attr: - self.add_edge(getattr(obj, source_attr), obj) + related_name = source_attr % { + 'class': source._meta.model_name, + 'app_label': source._meta.app_label, + } + self.add_edge(getattr(obj, related_name), obj) else: self.add_edge(None, obj) try: diff --git a/tests/admin_util/models.py b/tests/admin_util/models.py index 5e86f55a3a..05fb7c4efb 100644 --- a/tests/admin_util/models.py +++ b/tests/admin_util/models.py @@ -47,3 +47,18 @@ class Guest(models.Model): class EventGuide(models.Model): event = models.ForeignKey(Event, on_delete=models.DO_NOTHING) + + +class Vehicle(models.Model): + pass + + +class VehicleMixin(Vehicle): + vehicle = models.OneToOneField(Vehicle, parent_link=True, related_name='vehicle_%(app_label)s_%(class)s') + + class Meta: + abstract = True + + +class Car(VehicleMixin): + pass diff --git a/tests/admin_util/tests.py b/tests/admin_util/tests.py index b978a4ab05..4cb2d843fb 100644 --- a/tests/admin_util/tests.py +++ b/tests/admin_util/tests.py @@ -16,7 +16,7 @@ from django.utils.formats import localize from django.utils.safestring import mark_safe from django.utils import six -from .models import Article, Count, Event, Location, EventGuide +from .models import Article, Count, Event, Location, EventGuide, Vehicle, Car class NestedObjectsTests(TestCase): @@ -80,6 +80,16 @@ class NestedObjectsTests(TestCase): # One for Location, one for Guest, and no query for EventGuide n.collect(objs) + def test_relation_on_abstract(self): + """ + #21846 -- Check that `NestedObjects.collect()` doesn't trip + (AttributeError) on the special notation for relations on abstract + models (related_name that contains %(app_label)s and/or %(class)s). + """ + n = NestedObjects(using=DEFAULT_DB_ALIAS) + Car.objects.create() + n.collect([Vehicle.objects.first()]) + class UtilTests(SimpleTestCase): def test_values_from_lookup_field(self):