Review step 1 - simplify to clarify

This commit is contained in:
Jonathan Liuti 2015-12-18 13:24:45 +01:00
parent 7971343a64
commit 24ba3b3743
4 changed files with 13 additions and 54 deletions

View File

@ -58,45 +58,22 @@ class APIException(Exception):
return self.detail return self.detail
def build_error_from_django_validation_error(exc_info):
code = getattr(exc_info, 'code', None) or 'invalid'
return [
ValidationErrorMessage(msg, code=code)
for msg in exc_info.messages
]
# The recommended style for using `ValidationError` is to keep it namespaced # The recommended style for using `ValidationError` is to keep it namespaced
# under `serializers`, in order to minimize potential confusion with Django's # under `serializers`, in order to minimize potential confusion with Django's
# built in `ValidationError`. For example: # built in `ValidationError`. For example:
# #
# from rest_framework import serializers # from rest_framework import serializers
# raise serializers.ValidationError('Value was invalid') # raise serializers.ValidationError('Value was invalid')
class ValidationErrorMessage(six.text_type):
code = None
def __new__(cls, string, code=None, *args, **kwargs):
self = super(ValidationErrorMessage, cls).__new__(
cls, string, *args, **kwargs)
self.code = code
return self
class ValidationError(APIException): class ValidationError(APIException):
status_code = status.HTTP_400_BAD_REQUEST status_code = status.HTTP_400_BAD_REQUEST
def __init__(self, detail, code=None): def __init__(self, detail, code=None):
# If code is there, this means we are dealing with a message.
if code and not isinstance(detail, ValidationErrorMessage):
detail = ValidationErrorMessage(detail, code=code)
# For validation errors the 'detail' key is always required. # For validation errors the 'detail' key is always required.
# The details should always be coerced to a list if not already. # The details should always be coerced to a list if not already.
if not isinstance(detail, dict) and not isinstance(detail, list): if not isinstance(detail, dict) and not isinstance(detail, list):
detail = [detail] detail = [detail]
self.detail = _force_text_recursive(detail) self.detail = _force_text_recursive(detail)
self.code = code
def __str__(self): def __str__(self):
return six.text_type(self.detail) return six.text_type(self.detail)

View File

@ -32,7 +32,7 @@ from rest_framework.compat import (
unicode_to_repr unicode_to_repr
) )
from rest_framework.exceptions import ( from rest_framework.exceptions import (
ValidationError, build_error_from_django_validation_error ValidationError
) )
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
from rest_framework.utils import html, humanize_datetime, representation from rest_framework.utils import html, humanize_datetime, representation
@ -505,9 +505,7 @@ class Field(object):
raise raise
errors.extend(exc.detail) errors.extend(exc.detail)
except DjangoValidationError as exc: except DjangoValidationError as exc:
errors.extend( errors.extend(exc.messages)
build_error_from_django_validation_error(exc)
)
if errors: if errors:
raise ValidationError(errors) raise ValidationError(errors)

View File

@ -20,11 +20,9 @@ from django.db.models.fields import FieldDoesNotExist
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import exceptions
from rest_framework.compat import DurationField as ModelDurationField from rest_framework.compat import DurationField as ModelDurationField
from rest_framework.compat import JSONField as ModelJSONField from rest_framework.compat import JSONField as ModelJSONField
from rest_framework.compat import postgres_fields, unicode_to_repr from rest_framework.compat import postgres_fields, unicode_to_repr
from rest_framework.exceptions import ValidationErrorMessage
from rest_framework.utils import model_meta from rest_framework.utils import model_meta
from rest_framework.utils.field_mapping import ( from rest_framework.utils.field_mapping import (
ClassLookupDict, get_field_kwargs, get_nested_relation_kwargs, ClassLookupDict, get_field_kwargs, get_nested_relation_kwargs,
@ -221,6 +219,7 @@ class BaseSerializer(Field):
if self._errors and raise_exception: if self._errors and raise_exception:
raise ValidationError(self.errors) raise ValidationError(self.errors)
return not bool(self._errors) return not bool(self._errors)
@property @property
@ -301,8 +300,7 @@ def get_validation_error_detail(exc):
# exception class as well for simpler compat. # exception class as well for simpler compat.
# Eg. Calling Model.clean() explicitly inside Serializer.validate() # Eg. Calling Model.clean() explicitly inside Serializer.validate()
return { return {
api_settings.NON_FIELD_ERRORS_KEY: api_settings.NON_FIELD_ERRORS_KEY: list(exc.messages)
exceptions.build_error_from_django_validation_error(exc)
} }
elif isinstance(exc.detail, dict): elif isinstance(exc.detail, dict):
# If errors may be a dict we use the standard {key: list of values}. # If errors may be a dict we use the standard {key: list of values}.
@ -424,9 +422,8 @@ class Serializer(BaseSerializer):
message = self.error_messages['invalid'].format( message = self.error_messages['invalid'].format(
datatype=type(data).__name__ datatype=type(data).__name__
) )
error = ValidationErrorMessage(message, code='invalid')
raise ValidationError({ raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [error] api_settings.NON_FIELD_ERRORS_KEY: [message]
}) })
ret = OrderedDict() ret = OrderedDict()
@ -443,9 +440,7 @@ class Serializer(BaseSerializer):
except ValidationError as exc: except ValidationError as exc:
errors[field.field_name] = exc.detail errors[field.field_name] = exc.detail
except DjangoValidationError as exc: except DjangoValidationError as exc:
errors[field.field_name] = ( errors[field.field_name] = list(exc.messages)
exceptions.build_error_from_django_validation_error(exc)
)
except SkipField: except SkipField:
pass pass
else: else:
@ -580,18 +575,12 @@ class ListSerializer(BaseSerializer):
message = self.error_messages['not_a_list'].format( message = self.error_messages['not_a_list'].format(
input_type=type(data).__name__ input_type=type(data).__name__
) )
error = ValidationErrorMessage(
message,
code='not_a_list'
)
raise ValidationError({ raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [error] api_settings.NON_FIELD_ERRORS_KEY: [message]
}) })
if not self.allow_empty and len(data) == 0: if not self.allow_empty and len(data) == 0:
message = ValidationErrorMessage( message = self.error_messages['empty']
self.error_messages['empty'],
code='empty_not_allowed')
raise ValidationError({ raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message] api_settings.NON_FIELD_ERRORS_KEY: [message]
}) })

View File

@ -11,7 +11,7 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import unicode_to_repr from rest_framework.compat import unicode_to_repr
from rest_framework.exceptions import ValidationError, ValidationErrorMessage from rest_framework.exceptions import ValidationError
from rest_framework.utils.representation import smart_repr from rest_framework.utils.representation import smart_repr
@ -101,10 +101,7 @@ class UniqueTogetherValidator(object):
return return
missing = { missing = {
field_name: ValidationErrorMessage( field_name: self.missing_message
self.missing_message,
code='required')
for field_name in self.fields for field_name in self.fields
if field_name not in attrs if field_name not in attrs
} }
@ -190,9 +187,7 @@ class BaseUniqueForValidator(object):
'required' state on the fields they are applied to. 'required' state on the fields they are applied to.
""" """
missing = { missing = {
field_name: ValidationErrorMessage( field_name: self.missing_message
self.missing_message,
code='required')
for field_name in [self.field, self.date_field] for field_name in [self.field, self.date_field]
if field_name not in attrs if field_name not in attrs
} }
@ -219,7 +214,7 @@ class BaseUniqueForValidator(object):
if queryset.exists(): if queryset.exists():
message = self.message.format(date_field=self.date_field) message = self.message.format(date_field=self.date_field)
raise ValidationError({ raise ValidationError({
self.field: ValidationErrorMessage(message, code='unique'), self.field: message,
}) })
def __repr__(self): def __repr__(self):