diff options
| author | Tom Christie | 2013-01-04 13:50:40 +0000 |
|---|---|---|
| committer | Tom Christie | 2013-01-04 13:50:40 +0000 |
| commit | eb14278a3b08247c0aff5b2338a98203b51728c3 (patch) | |
| tree | a7ee5329f62b57d34c8e7de9f9bc73e35ec42896 /rest_framework/relations.py | |
| parent | 4c86fd46d772e1fd3789d9ed2a76b9b92cce0872 (diff) | |
| download | django-rest-framework-eb14278a3b08247c0aff5b2338a98203b51728c3.tar.bz2 | |
Add proper validation for updating relational fields with incorrect types. Fixes #446.
Diffstat (limited to 'rest_framework/relations.py')
| -rw-r--r-- | rest_framework/relations.py | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/rest_framework/relations.py b/rest_framework/relations.py index ae0d3de8..fcef42dd 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -276,6 +276,11 @@ class SlugRelatedField(RelatedField): default_read_only = False form_field_class = forms.ChoiceField + default_error_messages = { + 'does_not_exist': _("Object with %s=%s does not exist."), + 'invalid': _('Invalid value.'), + } + def __init__(self, *args, **kwargs): self.slug_field = kwargs.pop('slug_field', None) assert self.slug_field, 'slug_field is required' @@ -291,8 +296,11 @@ class SlugRelatedField(RelatedField): try: return self.queryset.get(**{self.slug_field: data}) except ObjectDoesNotExist: - raise ValidationError('Object with %s=%s does not exist.' % + raise ValidationError(self.error_messages['does_not_exist'] % (self.slug_field, unicode(data))) + except (TypeError, ValueError): + msg = self.error_messages['invalid'] + raise ValidationError(msg) class ManySlugRelatedField(ManyRelatedMixin, SlugRelatedField): @@ -311,6 +319,14 @@ class HyperlinkedRelatedField(RelatedField): default_read_only = False form_field_class = forms.ChoiceField + default_error_messages = { + 'no_match': _('Invalid hyperlink - No URL match'), + 'incorrect_match': _('Invalid hyperlink - Incorrect URL match'), + 'configuration_error': _('Invalid hyperlink due to configuration error'), + 'does_not_exist': _("Invalid hyperlink - object does not exist."), + 'invalid': _('Invalid value.'), + } + def __init__(self, *args, **kwargs): try: self.view_name = kwargs.pop('view_name') @@ -347,7 +363,7 @@ class HyperlinkedRelatedField(RelatedField): slug = getattr(obj, self.slug_field, None) if not slug: - raise ValidationError('Could not resolve URL for field using view name "%s"' % view_name) + raise Exception('Could not resolve URL for field using view name "%s"' % view_name) kwargs = {self.slug_url_kwarg: slug} try: @@ -361,7 +377,7 @@ class HyperlinkedRelatedField(RelatedField): except: pass - raise ValidationError('Could not resolve URL for field using view name "%s"' % view_name) + raise Exception('Could not resolve URL for field using view name "%s"' % view_name) def from_native(self, value): # Convert URL -> model instance pk @@ -369,7 +385,13 @@ class HyperlinkedRelatedField(RelatedField): if self.queryset is None: raise Exception('Writable related fields must include a `queryset` argument') - if value.startswith('http:') or value.startswith('https:'): + try: + http_prefix = value.startswith('http:') or value.startswith('https:') + except AttributeError: + msg = self.error_messages['invalid'] + raise ValidationError(msg) + + if http_prefix: # If needed convert absolute URLs to relative path value = urlparse(value).path prefix = get_script_prefix() @@ -379,10 +401,10 @@ class HyperlinkedRelatedField(RelatedField): try: match = resolve(value) except: - raise ValidationError('Invalid hyperlink - No URL match') + raise ValidationError(self.error_messages['no_match']) if match.url_name != self.view_name: - raise ValidationError('Invalid hyperlink - Incorrect URL match') + raise ValidationError(self.error_messages['incorrect_match']) pk = match.kwargs.get(self.pk_url_kwarg, None) slug = match.kwargs.get(self.slug_url_kwarg, None) @@ -394,14 +416,18 @@ class HyperlinkedRelatedField(RelatedField): elif slug is not None: slug_field = self.get_slug_field() queryset = self.queryset.filter(**{slug_field: slug}) - # If none of those are defined, it's an error. + # If none of those are defined, it's probably a configuation error. else: - raise ValidationError('Invalid hyperlink') + raise ValidationError(self.error_messages['configuration_error']) try: obj = queryset.get() except ObjectDoesNotExist: - raise ValidationError('Invalid hyperlink - object does not exist.') + raise ValidationError(self.error_messages['does_not_exist']) + except (TypeError, ValueError): + msg = self.error_messages['invalid'] + raise ValidationError(msg) + return obj @@ -460,7 +486,7 @@ class HyperlinkedIdentityField(Field): slug = getattr(obj, self.slug_field, None) if not slug: - raise ValidationError('Could not resolve URL for field using view name "%s"' % view_name) + raise Exception('Could not resolve URL for field using view name "%s"' % view_name) kwargs = {self.slug_url_kwarg: slug} try: @@ -474,4 +500,4 @@ class HyperlinkedIdentityField(Field): except: pass - raise ValidationError('Could not resolve URL for field using view name "%s"' % view_name) + raise Exception('Could not resolve URL for field using view name "%s"' % view_name) |
