Browse Source

Fixed #20777 -- Admin proxy model deletion regression

Added proxy_models tests by Harm Geerts <github@geertswei.nl>.
Anssi Kääriäinen 11 years ago
parent
commit
3844089edc

+ 0 - 3
django/contrib/admin/util.py

@@ -155,9 +155,6 @@ 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)

+ 3 - 3
docs/ref/models/instances.txt

@@ -500,9 +500,9 @@ using ``__str__()`` like this::
 .. method:: Model.__eq__()
 
 The equality method is defined such that instances with the same primary
-key value and the same concrete class are considered equal. The term
-concrete class means proxy model's first non-proxy parent or the class
-itself if it isn't a proxy class.
+key value and the same concrete class are considered equal. For proxy
+models, concrete class is defined as the model's first non-proxy parent;
+for all other models it is simply the model's class.
 
 For example::
 

+ 6 - 0
tests/proxy_models/admin.py

@@ -0,0 +1,6 @@
+from django.contrib import admin
+
+from .models import TrackerUser, ProxyTrackerUser
+
+admin.site.register(TrackerUser)
+admin.site.register(ProxyTrackerUser)

+ 19 - 1
tests/proxy_models/fixtures/myhorses.json

@@ -1,4 +1,22 @@
 [
+    {
+        "pk": 100,
+        "model": "auth.user",
+        "fields": {
+            "username": "super",
+            "first_name": "Super",
+            "last_name": "User",
+            "is_active": true,
+            "is_superuser": true,
+            "is_staff": true,
+            "last_login": "2007-05-30 13:20:10",
+            "groups": [],
+            "user_permissions": [],
+            "password": "sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158",
+            "email": "super@example.com",
+            "date_joined": "2007-05-30 13:20:10"
+        }
+    },
     {
         "pk": 100,
         "model": "proxy_models.BaseUser",
@@ -21,4 +39,4 @@
             "assignee": 100
         }
     }
-]
+]

+ 5 - 1
tests/proxy_models/models.py

@@ -117,9 +117,13 @@ class StateProxy(State):
 
 # Proxy models still works with filters (on related fields)
 # and select_related, even when mixed with model inheritance
+@python_2_unicode_compatible
 class BaseUser(models.Model):
     name = models.CharField(max_length=255)
 
+    def __str__(self):
+        return ':'.join((self.__class__.__name__, self.name,))
+
 class TrackerUser(BaseUser):
     status = models.CharField(max_length=50)
 
@@ -134,7 +138,7 @@ class Issue(models.Model):
     assignee = models.ForeignKey(TrackerUser)
 
     def __str__(self):
-        return ':'.join((self.__class__.__name__,self.summary,))
+        return ':'.join((self.__class__.__name__, self.summary,))
 
 class Bug(Issue):
     version = models.CharField(max_length=50)

+ 27 - 0
tests/proxy_models/tests.py

@@ -10,12 +10,14 @@ from django.db import models, DEFAULT_DB_ALIAS
 from django.db.models import signals
 from django.db.models.loading import cache
 from django.test import TestCase
+from django.test.utils import override_settings
 
 
 from .models import (MyPerson, Person, StatusPerson, LowerStatusPerson,
     MyPersonProxy, Abstract, OtherPerson, User, UserProxy, UserProxyProxy,
     Country, State, StateProxy, TrackerUser, BaseUser, Bug, ProxyTrackerUser,
     Improvement, ProxyProxyBug, ProxyBug, ProxyImprovement, Issue)
+from .admin import admin as force_admin_model_registration
 
 
 class ProxyModelTests(TestCase):
@@ -366,8 +368,10 @@ class ProxyModelTests(TestCase):
         self.assertEqual(MyPerson(id=100), Person(id=100))
 
 
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
 class ProxyModelAdminTests(TestCase):
     fixtures = ['myhorses']
+    urls = 'proxy_models.urls'
 
     def test_cascade_delete_proxy_model_admin_warning(self):
         """
@@ -383,3 +387,26 @@ class ProxyModelAdminTests(TestCase):
         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, ()))
+
+    def test_delete_str_in_model_admin(self):
+        """
+        Test if the admin delete page shows the correct string representation
+        for a proxy model.
+        """
+        user = TrackerUser.objects.get(name='Django Pony')
+        proxy = ProxyTrackerUser.objects.get(name='Django Pony')
+
+        user_str = (
+            'Tracker user: <a href="/admin/proxy_models/trackeruser/%s/">%s</a>' % (user.pk, user))
+        proxy_str = (
+            'Proxy tracker user: <a href="/admin/proxy_models/proxytrackeruser/%s/">%s</a>' %
+            (proxy.pk, proxy))
+
+        self.client.login(username='super', password='secret')
+        response = self.client.get('/admin/proxy_models/trackeruser/%s/delete/' % (user.pk,))
+        delete_str = response.context['deleted_objects'][0]
+        self.assertEqual(delete_str, user_str)
+        response = self.client.get('/admin/proxy_models/proxytrackeruser/%s/delete/' % (proxy.pk,))
+        delete_str = response.context['deleted_objects'][0]
+        self.assertEqual(delete_str, proxy_str)
+        self.client.logout()

+ 7 - 0
tests/proxy_models/urls.py

@@ -0,0 +1,7 @@
+from django.conf.urls import patterns, include
+
+from django.contrib import admin
+
+urlpatterns = patterns('',
+    (r'^admin/', include(admin.site.urls)),
+)