Author: julien
Date: 2012-01-02 10:02:47 -0800 (Mon, 02 Jan 2012)
New Revision: 17328

Modified:
   django/trunk/django/contrib/contenttypes/tests.py
   django/trunk/django/contrib/contenttypes/views.py
Log:
Fixed #8997 -- Prevented the contenttypes `shortcut` view to hide errors 
occurring inside the `get_absolute_url()` method. Thanks to Rob for the report 
and to joshlory, Aymeric Augustin and Claude Paroz for the patch.

Modified: django/trunk/django/contrib/contenttypes/tests.py
===================================================================
--- django/trunk/django/contrib/contenttypes/tests.py   2012-01-02 15:35:16 UTC 
(rev 17327)
+++ django/trunk/django/contrib/contenttypes/tests.py   2012-01-02 18:02:47 UTC 
(rev 17328)
@@ -30,7 +30,14 @@
     def get_absolute_url(self):
         return "/users/%s/" % urllib.quote(smart_str(self.name))
 
+class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
+    """
+    Fake model defining a ``get_absolute_url`` method containing an error
+    """
 
+    def get_absolute_url(self):
+        return "/users/%s/" % self.unknown_field
+
 class ContentTypesTests(TestCase):
 
     def setUp(self):
@@ -135,6 +142,22 @@
 
         self.assertRaises(Http404, shortcut, request, user_ct.id, obj.id)
 
+    def test_shortcut_view_with_broken_get_absolute_url(self):
+        """
+        Check that the shortcut view does not catch an AttributeError raised
+        by the model's get_absolute_url method.
+        Refs #8997.
+        """
+        request = HttpRequest()
+        request.META = {
+            "SERVER_NAME": "Example.com",
+            "SERVER_PORT": "80",
+        }
+        user_ct = ContentType.objects.get_for_model(FooWithBrokenAbsoluteUrl)
+        obj = FooWithBrokenAbsoluteUrl.objects.create(name="john")
+
+        self.assertRaises(AttributeError, shortcut, request, user_ct.id, 
obj.id)
+
     def test_missing_model(self):
         """
         Ensures that displaying content types in admin (or anywhere) doesn't

Modified: django/trunk/django/contrib/contenttypes/views.py
===================================================================
--- django/trunk/django/contrib/contenttypes/views.py   2012-01-02 15:35:16 UTC 
(rev 17327)
+++ django/trunk/django/contrib/contenttypes/views.py   2012-01-02 18:02:47 UTC 
(rev 17328)
@@ -4,19 +4,25 @@
 from django.core.exceptions import ObjectDoesNotExist
 
 def shortcut(request, content_type_id, object_id):
-    "Redirect to an object's page based on a content-type ID and an object ID."
+    """
+    Redirect to an object's page based on a content-type ID and an object ID.
+    """
     # Look up the object, making sure it's got a get_absolute_url() function.
     try:
         content_type = ContentType.objects.get(pk=content_type_id)
         if not content_type.model_class():
-            raise http.Http404("Content type %s object has no associated 
model" % content_type_id)
+            raise http.Http404("Content type %s object has no associated model"
+                               % content_type_id)
         obj = content_type.get_object_for_this_type(pk=object_id)
     except (ObjectDoesNotExist, ValueError):
-        raise http.Http404("Content type %s object %s doesn't exist" % 
(content_type_id, object_id))
+        raise http.Http404("Content type %s object %s doesn't exist"
+                           % (content_type_id, object_id))
     try:
-        absurl = obj.get_absolute_url()
+        get_absolute_url = obj.get_absolute_url
     except AttributeError:
-        raise http.Http404("%s objects don't have get_absolute_url() methods" 
% content_type.name)
+        raise http.Http404("%s objects don't have a get_absolute_url() method"
+                           % content_type.name)
+    absurl = get_absolute_url()
 
     # Try to figure out the object's domain, so we can do a cross-site redirect
     # if necessary.
@@ -66,6 +72,7 @@
     # to whatever get_absolute_url() returned.
     if object_domain is not None:
         protocol = request.is_secure() and 'https' or 'http'
-        return http.HttpResponseRedirect('%s://%s%s' % (protocol, 
object_domain, absurl))
+        return http.HttpResponseRedirect('%s://%s%s'
+                                         % (protocol, object_domain, absurl))
     else:
         return http.HttpResponseRedirect(absurl)

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to