Loading django/contrib/admin/utils.py +6 −2 Original line number Diff line number Diff line Loading @@ -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: Loading tests/admin_util/models.py +15 −0 Original line number Diff line number Diff line Loading @@ -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 tests/admin_util/tests.py +11 −1 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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): Loading Loading
django/contrib/admin/utils.py +6 −2 Original line number Diff line number Diff line Loading @@ -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: Loading
tests/admin_util/models.py +15 −0 Original line number Diff line number Diff line Loading @@ -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
tests/admin_util/tests.py +11 −1 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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): Loading