Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #8997 -- Prevented the contenttypes `shortcut` view to hide err…

…ors occurring inside the `get_absolute_url()` method. Thanks to Rob for the report and to joshlory, Aymeric Augustin and Claude Paroz for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17328 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 6fa62b8166f00d6cf1160b84dce37416f0051f00 1 parent 07132fb
Julien Phalip authored
23  django/contrib/contenttypes/tests.py
@@ -30,6 +30,13 @@ class FooWithUrl(FooWithoutUrl):
30 30
     def get_absolute_url(self):
31 31
         return "/users/%s/" % urllib.quote(smart_str(self.name))
32 32
 
  33
+class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
  34
+    """
  35
+    Fake model defining a ``get_absolute_url`` method containing an error
  36
+    """
  37
+
  38
+    def get_absolute_url(self):
  39
+        return "/users/%s/" % self.unknown_field
33 40
 
34 41
 class ContentTypesTests(TestCase):
35 42
 
@@ -135,6 +142,22 @@ def test_shortcut_view_without_get_absolute_url(self):
135 142
 
136 143
         self.assertRaises(Http404, shortcut, request, user_ct.id, obj.id)
137 144
 
  145
+    def test_shortcut_view_with_broken_get_absolute_url(self):
  146
+        """
  147
+        Check that the shortcut view does not catch an AttributeError raised
  148
+        by the model's get_absolute_url method.
  149
+        Refs #8997.
  150
+        """
  151
+        request = HttpRequest()
  152
+        request.META = {
  153
+            "SERVER_NAME": "Example.com",
  154
+            "SERVER_PORT": "80",
  155
+        }
  156
+        user_ct = ContentType.objects.get_for_model(FooWithBrokenAbsoluteUrl)
  157
+        obj = FooWithBrokenAbsoluteUrl.objects.create(name="john")
  158
+
  159
+        self.assertRaises(AttributeError, shortcut, request, user_ct.id, obj.id)
  160
+
138 161
     def test_missing_model(self):
139 162
         """
140 163
         Ensures that displaying content types in admin (or anywhere) doesn't
19  django/contrib/contenttypes/views.py
@@ -4,19 +4,25 @@
4 4
 from django.core.exceptions import ObjectDoesNotExist
5 5
 
6 6
 def shortcut(request, content_type_id, object_id):
7  
-    "Redirect to an object's page based on a content-type ID and an object ID."
  7
+    """
  8
+    Redirect to an object's page based on a content-type ID and an object ID.
  9
+    """
8 10
     # Look up the object, making sure it's got a get_absolute_url() function.
9 11
     try:
10 12
         content_type = ContentType.objects.get(pk=content_type_id)
11 13
         if not content_type.model_class():
12  
-            raise http.Http404("Content type %s object has no associated model" % content_type_id)
  14
+            raise http.Http404("Content type %s object has no associated model"
  15
+                               % content_type_id)
13 16
         obj = content_type.get_object_for_this_type(pk=object_id)
14 17
     except (ObjectDoesNotExist, ValueError):
15  
-        raise http.Http404("Content type %s object %s doesn't exist" % (content_type_id, object_id))
  18
+        raise http.Http404("Content type %s object %s doesn't exist"
  19
+                           % (content_type_id, object_id))
16 20
     try:
17  
-        absurl = obj.get_absolute_url()
  21
+        get_absolute_url = obj.get_absolute_url
18 22
     except AttributeError:
19  
-        raise http.Http404("%s objects don't have get_absolute_url() methods" % content_type.name)
  23
+        raise http.Http404("%s objects don't have a get_absolute_url() method"
  24
+                           % content_type.name)
  25
+    absurl = get_absolute_url()
20 26
 
21 27
     # Try to figure out the object's domain, so we can do a cross-site redirect
22 28
     # if necessary.
@@ -66,6 +72,7 @@ def shortcut(request, content_type_id, object_id):
66 72
     # to whatever get_absolute_url() returned.
67 73
     if object_domain is not None:
68 74
         protocol = request.is_secure() and 'https' or 'http'
69  
-        return http.HttpResponseRedirect('%s://%s%s' % (protocol, object_domain, absurl))
  75
+        return http.HttpResponseRedirect('%s://%s%s'
  76
+                                         % (protocol, object_domain, absurl))
70 77
     else:
71 78
         return http.HttpResponseRedirect(absurl)

0 notes on commit 6fa62b8

Please sign in to comment.
Something went wrong with that request. Please try again.