diff --git a/django/contrib/contenttypes/views.py b/django/contrib/contenttypes/views.py index bfde73c567..4d950c14fb 100644 --- a/django/contrib/contenttypes/views.py +++ b/django/contrib/contenttypes/views.py @@ -1,7 +1,7 @@ from django.apps import apps from django.contrib.contenttypes.models import ContentType from django.contrib.sites.shortcuts import get_current_site -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.http import Http404, HttpResponseRedirect from django.utils.translation import gettext as _ @@ -19,7 +19,7 @@ def shortcut(request, content_type_id, object_id): % {"ct_id": content_type_id} ) obj = content_type.get_object_for_this_type(pk=object_id) - except (ObjectDoesNotExist, ValueError): + except (ObjectDoesNotExist, ValueError, ValidationError): raise Http404( _("Content type %(ct_id)s object %(obj_id)s doesn’t exist") % {"ct_id": content_type_id, "obj_id": object_id} diff --git a/tests/contenttypes_tests/models.py b/tests/contenttypes_tests/models.py index 5e40217c30..90a928fc2f 100644 --- a/tests/contenttypes_tests/models.py +++ b/tests/contenttypes_tests/models.py @@ -1,3 +1,4 @@ +import uuid from urllib.parse import quote from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation @@ -112,3 +113,10 @@ class ModelWithM2MToSite(models.Model): def get_absolute_url(self): return "/title/%s/" % quote(self.title) + + +class UUIDModel(models.Model): + id = models.UUIDField(primary_key=True, default=uuid.uuid4) + + def get_absolute_url(self): + return "/uuid/%s/" % self.pk diff --git a/tests/contenttypes_tests/test_views.py b/tests/contenttypes_tests/test_views.py index 75f39a7bab..8cc11de3cb 100644 --- a/tests/contenttypes_tests/test_views.py +++ b/tests/contenttypes_tests/test_views.py @@ -19,6 +19,7 @@ from .models import ( SchemeIncludedURL, ) from .models import Site as MockSite +from .models import UUIDModel @override_settings(ROOT_URLCONF="contenttypes_tests.urls") @@ -263,3 +264,12 @@ class ShortcutViewTests(TestCase): obj = FooWithBrokenAbsoluteUrl.objects.create(name="john") with self.assertRaises(AttributeError): shortcut(self.request, user_ct.id, obj.id) + + def test_invalid_uuid_pk_raises_404(self): + content_type = ContentType.objects.get_for_model(UUIDModel) + invalid_uuid = "1234-zzzz-5678-0000-invaliduuid" + with self.assertRaisesMessage( + Http404, + f"Content type {content_type.id} object {invalid_uuid} doesn’t exist", + ): + shortcut(self.request, content_type.id, invalid_uuid)