Browse Source

Fixed #24940 -- Made model managers hashable

Thanks Federico Jaramillo Martínez for the report and Tim Graham for the
test and review.
Markus Holtermann 9 years ago
parent
commit
d3d66d4722

+ 3 - 0
django/db/models/manager.py

@@ -234,6 +234,9 @@ class BaseManager(object):
     def __ne__(self, other):
         return not (self == other)
 
+    def __hash__(self):
+        return id(self)
+
 
 class Manager(BaseManager.from_queryset(QuerySet)):
     pass

+ 3 - 0
docs/releases/1.8.3.txt

@@ -74,3 +74,6 @@ Bugfixes
 
 * Fixed crash when uploading images with MIME types that Pillow doesn't detect,
   such as bitmap, in ``forms.ImageField`` (:ticket:`24948`).
+
+* Fixed a regression when deleting a model through the admin that has a
+  ``GenericRelation`` with a ``related_query_name`` (:ticket:`24940`).

+ 1 - 1
tests/generic_inline_admin/models.py

@@ -48,7 +48,7 @@ class PhoneNumber(models.Model):
 
 class Contact(models.Model):
     name = models.CharField(max_length=50)
-    phone_numbers = GenericRelation(PhoneNumber)
+    phone_numbers = GenericRelation(PhoneNumber, related_query_name='phone_numbers')
 
 
 #

+ 13 - 1
tests/generic_inline_admin/tests.py

@@ -8,6 +8,7 @@ from django.contrib.admin.sites import AdminSite
 from django.contrib.auth.models import User
 from django.contrib.contenttypes.admin import GenericTabularInline
 from django.contrib.contenttypes.forms import generic_inlineformset_factory
+from django.contrib.contenttypes.models import ContentType
 from django.core.urlresolvers import reverse
 from django.forms.formsets import DEFAULT_MAX_NUM
 from django.forms.models import ModelForm
@@ -16,7 +17,7 @@ from django.test import (
 )
 
 from .admin import MediaInline, MediaPermanentInline, site as admin_site
-from .models import Category, Episode, EpisodePermanent, Media
+from .models import Category, Episode, EpisodePermanent, Media, PhoneNumber
 
 
 class TestDataMixin(object):
@@ -313,6 +314,17 @@ class GenericInlineAdminWithUniqueTogetherTest(TestDataMixin, TestCase):
         response = self.client.post(reverse('admin:generic_inline_admin_contact_add'), post_data)
         self.assertEqual(response.status_code, 302)  # redirect somewhere
 
+    def test_delete(self):
+        from .models import Contact
+        c = Contact.objects.create(name='foo')
+        PhoneNumber.objects.create(
+            object_id=c.id,
+            content_type=ContentType.objects.get_for_model(Contact),
+            phone_number="555-555-5555",
+        )
+        response = self.client.post(reverse('admin:generic_inline_admin_contact_delete', args=[c.pk]))
+        self.assertContains(response, 'Are you sure you want to delete')
+
 
 @override_settings(ROOT_URLCONF="generic_inline_admin.urls")
 class NoInlineDeletionTest(SimpleTestCase):