From 2b48fcc607010065c0f8107baf669dd41b164f3c Mon Sep 17 00:00:00 2001
From: Honza Kral <honza.kral@gmail.com>
Date: Sat, 23 Feb 2013 23:20:34 +0100
Subject: [PATCH] Fixed #18491 -- deleting a proxy doesn't show warning about
 cascade deletes

---
 django/contrib/admin/util.py                  |  3 ++
 setup.py                                      |  2 +-
 .../proxy_models/fixtures/myhorses.json       | 24 ++++++++++++++++
 tests/modeltests/proxy_models/tests.py        | 28 ++++++++++++++++++-
 4 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 tests/modeltests/proxy_models/fixtures/myhorses.json

diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
index 133a8ad13e..97858e688e 100644
--- a/django/contrib/admin/util.py
+++ b/django/contrib/admin/util.py
@@ -154,6 +154,9 @@ class NestedObjects(Collector):
             if source_attr:
                 self.add_edge(getattr(obj, source_attr), obj)
             else:
+                if obj._meta.proxy:
+                    # Take concrete model's instance to avoid mismatch in edges
+                    obj = obj._meta.concrete_model(pk=obj.pk)
                 self.add_edge(None, obj)
         try:
             return super(NestedObjects, self).collect(objs, source_attr=source_attr, **kwargs)
diff --git a/setup.py b/setup.py
index 6fff26d3af..2c11351bbc 100644
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-from distutils.core import setup
+from setuptools import setup
 from distutils.command.install_data import install_data
 from distutils.command.install import INSTALL_SCHEMES
 from distutils.sysconfig import get_python_lib
diff --git a/tests/modeltests/proxy_models/fixtures/myhorses.json b/tests/modeltests/proxy_models/fixtures/myhorses.json
new file mode 100644
index 0000000000..15943064c8
--- /dev/null
+++ b/tests/modeltests/proxy_models/fixtures/myhorses.json
@@ -0,0 +1,24 @@
+[
+    {
+        "pk": 100,
+        "model": "proxy_models.BaseUser",
+        "fields": {
+            "name": "Django Pony"
+        }
+    },
+    {
+        "pk": 100,
+        "model": "proxy_models.TrackerUser",
+        "fields": {
+            "status": "emperor"
+        }
+    },
+    {
+        "pk": 100,
+        "model": "proxy_models.Issue",
+        "fields": {
+            "summary": "Pony's Issue",
+            "assignee": 100
+        }
+    }
+]
\ No newline at end of file
diff --git a/tests/modeltests/proxy_models/tests.py b/tests/modeltests/proxy_models/tests.py
index d1c95467ee..c0b67c29d1 100644
--- a/tests/modeltests/proxy_models/tests.py
+++ b/tests/modeltests/proxy_models/tests.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
 import copy
 
 from django.conf import settings
+from django.contrib import admin
 from django.contrib.contenttypes.models import ContentType
 from django.core import management
 from django.core.exceptions import FieldError
@@ -14,7 +15,7 @@ from django.test import TestCase
 from .models import (MyPerson, Person, StatusPerson, LowerStatusPerson,
     MyPersonProxy, Abstract, OtherPerson, User, UserProxy, UserProxyProxy,
     Country, State, StateProxy, TrackerUser, BaseUser, Bug, ProxyTrackerUser,
-    Improvement, ProxyProxyBug, ProxyBug, ProxyImprovement)
+    Improvement, ProxyProxyBug, ProxyBug, ProxyImprovement, Issue)
 
 
 class ProxyModelTests(TestCase):
@@ -360,3 +361,28 @@ class ProxyModelTests(TestCase):
         management.call_command('loaddata', 'mypeople.json', verbosity=0, commit=False)
         p = MyPerson.objects.get(pk=100)
         self.assertEqual(p.name, 'Elvis Presley')
+
+
+class ProxyModelAdminTests(TestCase):
+    def setUp(self):
+        management.call_command('loaddata', 'myhorses.json', verbosity=0,
+            commit=False)
+
+    def tearDown(self):
+        TrackerUser.objects.all().delete()
+        Issue.objects.all().delete()
+
+    def test_cascade_delete_proxy_model_admin_warning(self):
+        """
+        Test if admin gives warning about cascade deleting models referenced
+        to concrete model by deleting proxy object.
+        """
+        tracker_user = TrackerUser.objects.all()[0]
+        base_user = BaseUser.objects.all()[0]
+        issue = Issue.objects.all()[0]
+        with self.assertNumQueries(7):
+            collector = admin.util.NestedObjects('default')
+            collector.collect(ProxyTrackerUser.objects.all())
+        self.assertTrue(tracker_user in collector.edges.get(None, ()))
+        self.assertTrue(base_user in collector.edges.get(None, ()))
+        self.assertTrue(issue in collector.edges.get(tracker_user, ()))