mirror of https://github.com/django/django.git
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.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17328 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
07132fb5d4
commit
6fa62b8166
|
@ -30,6 +30,13 @@ class FooWithUrl(FooWithoutUrl):
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return "/users/%s/" % urllib.quote(smart_str(self.name))
|
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):
|
class ContentTypesTests(TestCase):
|
||||||
|
|
||||||
|
@ -135,6 +142,22 @@ class ContentTypesTests(TestCase):
|
||||||
|
|
||||||
self.assertRaises(Http404, shortcut, request, user_ct.id, obj.id)
|
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):
|
def test_missing_model(self):
|
||||||
"""
|
"""
|
||||||
Ensures that displaying content types in admin (or anywhere) doesn't
|
Ensures that displaying content types in admin (or anywhere) doesn't
|
||||||
|
|
|
@ -4,19 +4,25 @@ from django.contrib.sites.models import Site, get_current_site
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
def shortcut(request, content_type_id, object_id):
|
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.
|
# Look up the object, making sure it's got a get_absolute_url() function.
|
||||||
try:
|
try:
|
||||||
content_type = ContentType.objects.get(pk=content_type_id)
|
content_type = ContentType.objects.get(pk=content_type_id)
|
||||||
if not content_type.model_class():
|
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)
|
obj = content_type.get_object_for_this_type(pk=object_id)
|
||||||
except (ObjectDoesNotExist, ValueError):
|
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:
|
try:
|
||||||
absurl = obj.get_absolute_url()
|
get_absolute_url = obj.get_absolute_url
|
||||||
except AttributeError:
|
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
|
# Try to figure out the object's domain, so we can do a cross-site redirect
|
||||||
# if necessary.
|
# if necessary.
|
||||||
|
@ -66,6 +72,7 @@ def shortcut(request, content_type_id, object_id):
|
||||||
# to whatever get_absolute_url() returned.
|
# to whatever get_absolute_url() returned.
|
||||||
if object_domain is not None:
|
if object_domain is not None:
|
||||||
protocol = request.is_secure() and 'https' or 'http'
|
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:
|
else:
|
||||||
return http.HttpResponseRedirect(absurl)
|
return http.HttpResponseRedirect(absurl)
|
||||||
|
|
Loading…
Reference in New Issue