Commit 6fa62b81 authored by Julien Phalip's avatar Julien Phalip
Browse files

Fixed #8997 -- Prevented the contenttypes `shortcut` view to hide errors...

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
parent 07132fb5
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -30,6 +30,13 @@ class FooWithUrl(FooWithoutUrl):
    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):

@@ -135,6 +142,22 @@ class ContentTypesTests(TestCase):

        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
+13 −6
Original line number Diff line number Diff line
@@ -4,19 +4,25 @@ from django.contrib.sites.models import Site, get_current_site
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 @@ def shortcut(request, content_type_id, object_id):
    # 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)