Only catch TypeError/ValueError for object lookups

This commit is contained in:
Ryan P Kilby 2018-06-13 12:04:20 -04:00 committed by Carlton Gibson
parent 9b8af04e7f
commit 7c834f25e4
2 changed files with 35 additions and 2 deletions

View File

@ -1,6 +1,7 @@
# coding: utf-8
from __future__ import unicode_literals
import sys
from collections import OrderedDict
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
@ -31,6 +32,20 @@ def method_overridden(method_name, klass, instance):
return default_method is not getattr(instance, method_name).__func__
class ObjectValueError(ValueError):
"""
Raised when `queryset.get()` failed due to an underlying `ValueError`.
Wrapping prevents calling code conflating this with unrelated errors.
"""
class ObjectTypeError(TypeError):
"""
Raised when `queryset.get()` failed due to an underlying `TypeError`.
Wrapping prevents calling code conflating this with unrelated errors.
"""
class Hyperlink(six.text_type):
"""
A string like object that additionally has an associated name.
@ -296,7 +311,16 @@ class HyperlinkedRelatedField(RelatedField):
"""
lookup_value = view_kwargs[self.lookup_url_kwarg]
lookup_kwargs = {self.lookup_field: lookup_value}
return self.get_queryset().get(**lookup_kwargs)
queryset = self.get_queryset()
try:
return queryset.get(**lookup_kwargs)
except ValueError:
exc = ObjectValueError(str(sys.exc_info()[1]))
six.reraise(type(exc), exc, sys.exc_info()[2])
except TypeError:
exc = ObjectTypeError(str(sys.exc_info()[1]))
six.reraise(type(exc), exc, sys.exc_info()[2])
def get_url(self, obj, view_name, request, format):
"""
@ -346,7 +370,7 @@ class HyperlinkedRelatedField(RelatedField):
try:
return self.get_object(match.view_name, match.args, match.kwargs)
except (ObjectDoesNotExist, TypeError, ValueError):
except (ObjectDoesNotExist, ObjectValueError, ObjectTypeError):
self.fail('does_not_exist')
def to_representation(self, value):

View File

@ -197,6 +197,15 @@ class TestHyperlinkedRelatedField(APISimpleTestCase):
msg = excinfo.value.detail[0]
assert msg == 'Invalid hyperlink - Object does not exist.'
def test_hyperlinked_related_internal_type_error(self):
class Field(serializers.HyperlinkedRelatedField):
def get_object(self, incorrect, signature):
pass
field = Field(view_name='example', queryset=self.queryset)
with pytest.raises(TypeError):
field.to_internal_value('http://example.org/example/doesnotexist/')
class TestHyperlinkedIdentityField(APISimpleTestCase):
def setUp(self):