Ticket #10927: 10927.diff

File 10927.diff, 3.7 KB (added by jdunck, 6 years ago)

More robust shortcut view, with tests.

  • django/contrib/contenttypes/views.py

    diff --git a/django/contrib/contenttypes/views.py b/django/contrib/contenttypes/views.py
    index 4285be3..07800cb 100644
    a b  
    11from django import http
    22from django.contrib.contenttypes.models import ContentType
    33from django.contrib.sites.models import Site
    4 from django.core.exceptions import ObjectDoesNotExist
     4from django.core.exceptions import ObjectDoesNotExist, ValidationError
    55
    66def shortcut(request, content_type_id, object_id):
    77    "Redirect to an object's page based on a content-type ID and an object ID."
    88    # Look up the object, making sure it's got a get_absolute_url() function.
     9    def raise_invalid():
     10        raise http.Http404("Content type %s object %s doesn't exist" % (content_type_id, object_id))
     11    try:
     12        content_type_id = int(content_type_id)
     13    except ValueError:
     14        raise_invalid()
    915    try:
    1016        content_type = ContentType.objects.get(pk=content_type_id)
     17    except ObjectDoesNotExist:
     18        raise_invalid()
     19    try:
     20        object_id = content_type.model_class()._meta.pk.to_python(object_id)
     21    except ValidationError:
     22        raise_invalid()
     23    try:
    1124        obj = content_type.get_object_for_this_type(pk=object_id)
    1225    except ObjectDoesNotExist:
    13         raise http.Http404("Content type %s object %s doesn't exist" % (content_type_id, object_id))
     26        raise_invalid()
    1427    try:
    1528        absurl = obj.get_absolute_url()
    1629    except AttributeError:
  • tests/regressiontests/views/tests/defaults.py

    diff --git a/tests/regressiontests/views/tests/defaults.py b/tests/regressiontests/views/tests/defaults.py
    index bf490d7..bef80e4 100644
    a b class DefaultsTests(TestCase): 
    1010    """Test django views in django/views/defaults.py"""
    1111    fixtures = ['testdata.json']
    1212
    13     def test_shorcut_with_absolute_url(self):
     13    def test_shortcut_with_absolute_url(self):
    1414        "Can view a shortcut an Author object that has with a get_absolute_url method"
    1515        for obj in Author.objects.all():
    1616            short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, obj.pk)
    class DefaultsTests(TestCase): 
    2525            response = self.client.get(short_url)
    2626            self.assertEquals(response.status_code, 404)
    2727
     28    def test_wrong_type_pk(self):
     29        an_article = Article.objects.all()[0]
     30        short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Article).id, 'nobody/expects')
     31        response = self.client.get(short_url)
     32        self.assertEquals(response.status_code, 404)
     33
     34    def test_shortcut_bad_pk(self):
     35        "Shortcuts for an object that has with a get_absolute_url method raises 404"
     36        short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Article).id, '4242424242')
     37        response = self.client.get(short_url)
     38        self.assertEquals(response.status_code, 404)
     39
     40    def test_nonint_content_type(self):
     41        an_article = Article.objects.all()[0]
     42        short_url = '/views/shortcut/%s/%s/' % ('spam', an_article.pk)
     43        response = self.client.get(short_url)
     44        self.assertEquals(response.status_code, 404)
     45
     46    def test_bad_content_type(self):
     47        an_article = Article.objects.all()[0]
     48        short_url = '/views/shortcut/%s/%s/' % (4242424242, an_article.pk)
     49        response = self.client.get(short_url)
     50        self.assertEquals(response.status_code, 404)
     51
    2852    def test_page_not_found(self):
    2953        "A 404 status is returned by the page_not_found view"
    3054        non_existing_urls = ['/views/non_existing_url/', # this is in urls.py
Back to Top