diff --git a/django/contrib/admin/utils.py b/django/contrib/admin/utils.py index 2337fe62a5..e85e2de0d3 100644 --- a/django/contrib/admin/utils.py +++ b/django/contrib/admin/utils.py @@ -163,8 +163,9 @@ def get_deleted_objects(objs, opts, user, admin_site, using): to_delete = collector.nested(format_callback) protected = [format_callback(obj) for obj in collector.protected] + model_count = {model._meta.verbose_name_plural: len(objs) for model, objs in collector.model_objs.items()} - return to_delete, collector.model_count, perms_needed, protected + return to_delete, model_count, perms_needed, protected class NestedObjects(Collector): @@ -172,7 +173,7 @@ class NestedObjects(Collector): super(NestedObjects, self).__init__(*args, **kwargs) self.edges = {} # {from_instance: [to_instances]} self.protected = set() - self.model_count = defaultdict(int) + self.model_objs = defaultdict(set) def add_edge(self, source, target): self.edges.setdefault(source, []).append(target) @@ -187,7 +188,7 @@ class NestedObjects(Collector): self.add_edge(getattr(obj, related_name), obj) else: self.add_edge(None, obj) - self.model_count[obj._meta.verbose_name_plural] += 1 + self.model_objs[obj._meta.model].add(obj) try: return super(NestedObjects, self).collect(objs, source_attr=source_attr, **kwargs) except models.ProtectedError as e: diff --git a/docs/releases/1.9.1.txt b/docs/releases/1.9.1.txt index 3c987c3428..60b793f3e9 100644 --- a/docs/releases/1.9.1.txt +++ b/docs/releases/1.9.1.txt @@ -26,3 +26,6 @@ Bugfixes * Fixed missing ``varchar/text_pattern_ops`` index on ``CharField`` and ``TextField`` respectively when using ``AlterField`` on PostgreSQL (:ticket:`25412`). + +* Fixed admin's delete confirmation page's summary counts of related objects + (:ticket:`25883`). diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py index 3ecaf57b6d..9a6b63230a 100644 --- a/tests/admin_views/models.py +++ b/tests/admin_views/models.py @@ -40,6 +40,7 @@ class Article(models.Model): content = models.TextField() date = models.DateTimeField() section = models.ForeignKey(Section, models.CASCADE, null=True, blank=True) + another_section = models.ForeignKey(Section, models.CASCADE, null=True, blank=True, related_name='+') sub_section = models.ForeignKey(Section, models.SET_NULL, null=True, blank=True, related_name='+') def __str__(self): diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index db960b34b0..00e23302e1 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -1292,7 +1292,8 @@ class AdminViewPermissionsTest(TestCase): ) cls.s1 = Section.objects.create(name='Test section') cls.a1 = Article.objects.create( - content='

Middle content

', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1 + content='

Middle content

', date=datetime.datetime(2008, 3, 18, 11, 54, 58), section=cls.s1, + another_section=cls.s1, ) cls.a2 = Article.objects.create( content='

Oldest content

', date=datetime.datetime(2000, 3, 18, 11, 54, 58), section=cls.s1 @@ -3203,7 +3204,7 @@ class AdminActionsTest(TestCase): self.assertIsInstance(confirmation, TemplateResponse) self.assertContains(confirmation, "Are you sure you want to delete the selected subscribers?") self.assertContains(confirmation, "

Summary

") - self.assertContains(confirmation, "
  • Subscribers: 3
  • ") + self.assertContains(confirmation, "
  • Subscribers: 2
  • ") self.assertContains(confirmation, "
  • External subscribers: 1
  • ") self.assertContains(confirmation, ACTION_CHECKBOX_NAME, count=2) self.client.post(reverse('admin:admin_views_subscriber_changelist'), delete_confirmation_data)