mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-26 03:23:59 +03:00
Use serializers.ValidationError
This commit is contained in:
parent
5882a7a9d5
commit
05cbec9dd7
|
@ -144,11 +144,15 @@ The corresponding code would now look like this:
|
|||
logging.info('Creating ticket "%s"' % name)
|
||||
serializer.save(user=request.user) # Include the user when saving.
|
||||
|
||||
#### Use `rest_framework.exceptions.ValidationFailed`.
|
||||
#### Using `serializers.ValidationError`.
|
||||
|
||||
Django's `ValidationError` class is intended for use with HTML forms and it's API makes its use slightly awkward with nested validation errors as can occur in serializers.
|
||||
Previously `serializers.ValidationError` error was simply a synonym for `django.core.exceptions.ValidationError`. This has now been altered so that it inherits from the standard `APIException` base class.
|
||||
|
||||
We now include a simpler `ValidationFailed` exception class in REST framework that you should use when raising validation failures.
|
||||
The reason behind this is that Django's `ValidationError` class is intended for use with HTML forms and its API makes using it slightly awkward with nested validation errors that can occur in serializers.
|
||||
|
||||
For most users this change shouldn't require any updates to your codebase, but it is worth ensuring that whenever raising validation errors you are always using the `serializers.ValidationError` exception class, and not Django's built-in exception.
|
||||
|
||||
We strongly recommend that you use the namespaced import style of `import serializers` and not `from serializers import ValidationError` in order to avoid any potential confusion.
|
||||
|
||||
#### Change to `validate_<field_name>`.
|
||||
|
||||
|
@ -156,14 +160,14 @@ The `validate_<field_name>` method hooks that can be attached to serializer clas
|
|||
|
||||
def validate_score(self, attrs, source):
|
||||
if attrs[score] % 10 != 0:
|
||||
raise ValidationError('This field should be a multiple of ten.')
|
||||
raise serializers.ValidationError('This field should be a multiple of ten.')
|
||||
return attrs
|
||||
|
||||
This is now simplified slightly, and the method hooks simply take the value to be validated, and return it's validated value.
|
||||
|
||||
def validate_score(self, value):
|
||||
if value % 10 != 0:
|
||||
raise ValidationError('This field should be a multiple of ten.')
|
||||
raise serializers.ValidationError('This field should be a multiple of ten.')
|
||||
return value
|
||||
|
||||
Any ad-hoc validation that applies to more than one field should go in the `.validate(self, attrs)` method as usual.
|
||||
|
|
|
@ -18,13 +18,13 @@ class AuthTokenSerializer(serializers.Serializer):
|
|||
if user:
|
||||
if not user.is_active:
|
||||
msg = _('User account is disabled.')
|
||||
raise exceptions.ValidationFailed(msg)
|
||||
raise exceptions.ValidationError(msg)
|
||||
else:
|
||||
msg = _('Unable to log in with provided credentials.')
|
||||
raise exceptions.ValidationFailed(msg)
|
||||
raise exceptions.ValidationError(msg)
|
||||
else:
|
||||
msg = _('Must include "username" and "password"')
|
||||
raise exceptions.ValidationFailed(msg)
|
||||
raise exceptions.ValidationError(msg)
|
||||
|
||||
attrs['user'] = user
|
||||
return attrs
|
||||
|
|
|
@ -24,7 +24,14 @@ class APIException(Exception):
|
|||
return self.detail
|
||||
|
||||
|
||||
class ValidationFailed(APIException):
|
||||
# The recommended style for using `ValidationError` is to keep it namespaced
|
||||
# under `serializers`, in order to minimize potential confusion with Django's
|
||||
# built in `ValidationError`. For example:
|
||||
#
|
||||
# from rest_framework import serializers
|
||||
# raise serializers.ValidationError('Value was invalid')
|
||||
|
||||
class ValidationError(APIException):
|
||||
status_code = status.HTTP_400_BAD_REQUEST
|
||||
|
||||
def __init__(self, detail):
|
||||
|
|
|
@ -13,7 +13,7 @@ from rest_framework.compat import (
|
|||
smart_text, EmailValidator, MinValueValidator, MaxValueValidator,
|
||||
MinLengthValidator, MaxLengthValidator, URLValidator
|
||||
)
|
||||
from rest_framework.exceptions import ValidationFailed
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.utils import html, representation, humanize_datetime
|
||||
import copy
|
||||
|
@ -102,7 +102,7 @@ NOT_READ_ONLY_DEFAULT = 'May not set both `read_only` and `default`'
|
|||
NOT_REQUIRED_DEFAULT = 'May not set both `required` and `default`'
|
||||
USE_READONLYFIELD = 'Field(read_only=True) should be ReadOnlyField'
|
||||
MISSING_ERROR_MESSAGE = (
|
||||
'ValidationFailed raised by `{class_name}`, but error key `{key}` does '
|
||||
'ValidationError raised by `{class_name}`, but error key `{key}` does '
|
||||
'not exist in the `error_messages` dictionary.'
|
||||
)
|
||||
|
||||
|
@ -264,7 +264,7 @@ class Field(object):
|
|||
def run_validators(self, value):
|
||||
"""
|
||||
Test the given value against all the validators on the field,
|
||||
and either raise a `ValidationFailed` or simply return.
|
||||
and either raise a `ValidationError` or simply return.
|
||||
"""
|
||||
errors = []
|
||||
for validator in self.validators:
|
||||
|
@ -272,12 +272,12 @@ class Field(object):
|
|||
validator.serializer_field = self
|
||||
try:
|
||||
validator(value)
|
||||
except ValidationFailed as exc:
|
||||
except ValidationError as exc:
|
||||
errors.extend(exc.detail)
|
||||
except DjangoValidationError as exc:
|
||||
errors.extend(exc.messages)
|
||||
if errors:
|
||||
raise ValidationFailed(errors)
|
||||
raise ValidationError(errors)
|
||||
|
||||
def validate(self, value):
|
||||
pass
|
||||
|
@ -305,7 +305,7 @@ class Field(object):
|
|||
msg = MISSING_ERROR_MESSAGE.format(class_name=class_name, key=key)
|
||||
raise AssertionError(msg)
|
||||
message_string = msg.format(**kwargs)
|
||||
raise ValidationFailed(message_string)
|
||||
raise ValidationError(message_string)
|
||||
|
||||
@property
|
||||
def root(self):
|
||||
|
|
|
@ -14,7 +14,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from django.db import models
|
||||
from django.utils import six
|
||||
from django.utils.datastructures import SortedDict
|
||||
from rest_framework.exceptions import ValidationFailed
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.fields import empty, set_value, Field, SkipField
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.utils import html, model_meta, representation
|
||||
|
@ -77,13 +77,6 @@ class BaseSerializer(Field):
|
|||
raise NotImplementedError('`create()` must be implemented.')
|
||||
|
||||
def save(self, **kwargs):
|
||||
assert not hasattr(self, 'restore_object'), (
|
||||
'Serializer %s has old-style version 2 `.restore_object()` '
|
||||
'that is no longer compatible with REST framework 3. '
|
||||
'Use the new-style `.create()` and `.update()` methods instead.' %
|
||||
self.__class__.__name__
|
||||
)
|
||||
|
||||
validated_data = self.validated_data
|
||||
if kwargs:
|
||||
validated_data = dict(
|
||||
|
@ -105,17 +98,24 @@ class BaseSerializer(Field):
|
|||
return self.instance
|
||||
|
||||
def is_valid(self, raise_exception=False):
|
||||
assert not hasattr(self, 'restore_object'), (
|
||||
'Serializer %s has old-style version 2 `.restore_object()` '
|
||||
'that is no longer compatible with REST framework 3. '
|
||||
'Use the new-style `.create()` and `.update()` methods instead.' %
|
||||
self.__class__.__name__
|
||||
)
|
||||
|
||||
if not hasattr(self, '_validated_data'):
|
||||
try:
|
||||
self._validated_data = self.run_validation(self._initial_data)
|
||||
except ValidationFailed as exc:
|
||||
except ValidationError as exc:
|
||||
self._validated_data = {}
|
||||
self._errors = exc.detail
|
||||
else:
|
||||
self._errors = {}
|
||||
|
||||
if self._errors and raise_exception:
|
||||
raise ValidationFailed(self._errors)
|
||||
raise ValidationError(self._errors)
|
||||
|
||||
return not bool(self._errors)
|
||||
|
||||
|
@ -124,6 +124,8 @@ class BaseSerializer(Field):
|
|||
if not hasattr(self, '_data'):
|
||||
if self.instance is not None and not getattr(self, '_errors', None):
|
||||
self._data = self.to_representation(self.instance)
|
||||
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
|
||||
self._data = self.to_representation(self.validated_data)
|
||||
else:
|
||||
self._data = self.get_initial()
|
||||
return self._data
|
||||
|
@ -329,7 +331,7 @@ class Serializer(BaseSerializer):
|
|||
return None
|
||||
|
||||
if not isinstance(data, dict):
|
||||
raise ValidationFailed({
|
||||
raise ValidationError({
|
||||
api_settings.NON_FIELD_ERRORS_KEY: ['Invalid data']
|
||||
})
|
||||
|
||||
|
@ -338,8 +340,8 @@ class Serializer(BaseSerializer):
|
|||
self.run_validators(value)
|
||||
value = self.validate(value)
|
||||
assert value is not None, '.validate() should return the validated data'
|
||||
except ValidationFailed as exc:
|
||||
raise ValidationFailed({
|
||||
except ValidationError as exc:
|
||||
raise ValidationError({
|
||||
api_settings.NON_FIELD_ERRORS_KEY: exc.detail
|
||||
})
|
||||
return value
|
||||
|
@ -359,7 +361,7 @@ class Serializer(BaseSerializer):
|
|||
validated_value = field.run_validation(primitive_value)
|
||||
if validate_method is not None:
|
||||
validated_value = validate_method(validated_value)
|
||||
except ValidationFailed as exc:
|
||||
except ValidationError as exc:
|
||||
errors[field.field_name] = exc.detail
|
||||
except SkipField:
|
||||
pass
|
||||
|
@ -367,7 +369,7 @@ class Serializer(BaseSerializer):
|
|||
set_value(ret, field.source_attrs, validated_value)
|
||||
|
||||
if errors:
|
||||
raise ValidationFailed(errors)
|
||||
raise ValidationError(errors)
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from decimal import Decimal
|
||||
from django.utils import timezone
|
||||
from rest_framework import exceptions, fields, serializers
|
||||
from rest_framework import serializers
|
||||
import datetime
|
||||
import django
|
||||
import pytest
|
||||
|
@ -17,8 +17,8 @@ class TestEmpty:
|
|||
"""
|
||||
By default a field must be included in the input.
|
||||
"""
|
||||
field = fields.IntegerField()
|
||||
with pytest.raises(exceptions.ValidationFailed) as exc_info:
|
||||
field = serializers.IntegerField()
|
||||
with pytest.raises(serializers.ValidationError) as exc_info:
|
||||
field.run_validation()
|
||||
assert exc_info.value.detail == ['This field is required.']
|
||||
|
||||
|
@ -26,16 +26,16 @@ class TestEmpty:
|
|||
"""
|
||||
If `required=False` then a field may be omitted from the input.
|
||||
"""
|
||||
field = fields.IntegerField(required=False)
|
||||
with pytest.raises(fields.SkipField):
|
||||
field = serializers.IntegerField(required=False)
|
||||
with pytest.raises(serializers.SkipField):
|
||||
field.run_validation()
|
||||
|
||||
def test_disallow_null(self):
|
||||
"""
|
||||
By default `None` is not a valid input.
|
||||
"""
|
||||
field = fields.IntegerField()
|
||||
with pytest.raises(exceptions.ValidationFailed) as exc_info:
|
||||
field = serializers.IntegerField()
|
||||
with pytest.raises(serializers.ValidationError) as exc_info:
|
||||
field.run_validation(None)
|
||||
assert exc_info.value.detail == ['This field may not be null.']
|
||||
|
||||
|
@ -43,7 +43,7 @@ class TestEmpty:
|
|||
"""
|
||||
If `allow_null=True` then `None` is a valid input.
|
||||
"""
|
||||
field = fields.IntegerField(allow_null=True)
|
||||
field = serializers.IntegerField(allow_null=True)
|
||||
output = field.run_validation(None)
|
||||
assert output is None
|
||||
|
||||
|
@ -51,8 +51,8 @@ class TestEmpty:
|
|||
"""
|
||||
By default '' is not a valid input.
|
||||
"""
|
||||
field = fields.CharField()
|
||||
with pytest.raises(exceptions.ValidationFailed) as exc_info:
|
||||
field = serializers.CharField()
|
||||
with pytest.raises(serializers.ValidationError) as exc_info:
|
||||
field.run_validation('')
|
||||
assert exc_info.value.detail == ['This field may not be blank.']
|
||||
|
||||
|
@ -60,7 +60,7 @@ class TestEmpty:
|
|||
"""
|
||||
If `allow_blank=True` then '' is a valid input.
|
||||
"""
|
||||
field = fields.CharField(allow_blank=True)
|
||||
field = serializers.CharField(allow_blank=True)
|
||||
output = field.run_validation('')
|
||||
assert output is ''
|
||||
|
||||
|
@ -68,7 +68,7 @@ class TestEmpty:
|
|||
"""
|
||||
If `default` is set, then omitted values get the default input.
|
||||
"""
|
||||
field = fields.IntegerField(default=123)
|
||||
field = serializers.IntegerField(default=123)
|
||||
output = field.run_validation()
|
||||
assert output is 123
|
||||
|
||||
|
@ -96,13 +96,13 @@ class TestSource:
|
|||
class TestReadOnly:
|
||||
def setup(self):
|
||||
class TestSerializer(serializers.Serializer):
|
||||
read_only = fields.ReadOnlyField()
|
||||
writable = fields.IntegerField()
|
||||
read_only = serializers.ReadOnlyField()
|
||||
writable = serializers.IntegerField()
|
||||
self.Serializer = TestSerializer
|
||||
|
||||
def test_validate_read_only(self):
|
||||
"""
|
||||
Read-only fields should not be included in validation.
|
||||
Read-only serializers.should not be included in validation.
|
||||
"""
|
||||
data = {'read_only': 123, 'writable': 456}
|
||||
serializer = self.Serializer(data=data)
|
||||
|
@ -111,7 +111,7 @@ class TestReadOnly:
|
|||
|
||||
def test_serialize_read_only(self):
|
||||
"""
|
||||
Read-only fields should be serialized.
|
||||
Read-only serializers.should be serialized.
|
||||
"""
|
||||
instance = {'read_only': 123, 'writable': 456}
|
||||
serializer = self.Serializer(instance)
|
||||
|
@ -121,13 +121,13 @@ class TestReadOnly:
|
|||
class TestWriteOnly:
|
||||
def setup(self):
|
||||
class TestSerializer(serializers.Serializer):
|
||||
write_only = fields.IntegerField(write_only=True)
|
||||
readable = fields.IntegerField()
|
||||
write_only = serializers.IntegerField(write_only=True)
|
||||
readable = serializers.IntegerField()
|
||||
self.Serializer = TestSerializer
|
||||
|
||||
def test_validate_write_only(self):
|
||||
"""
|
||||
Write-only fields should be included in validation.
|
||||
Write-only serializers.should be included in validation.
|
||||
"""
|
||||
data = {'write_only': 123, 'readable': 456}
|
||||
serializer = self.Serializer(data=data)
|
||||
|
@ -136,7 +136,7 @@ class TestWriteOnly:
|
|||
|
||||
def test_serialize_write_only(self):
|
||||
"""
|
||||
Write-only fields should not be serialized.
|
||||
Write-only serializers.should not be serialized.
|
||||
"""
|
||||
instance = {'write_only': 123, 'readable': 456}
|
||||
serializer = self.Serializer(instance)
|
||||
|
@ -146,8 +146,8 @@ class TestWriteOnly:
|
|||
class TestInitial:
|
||||
def setup(self):
|
||||
class TestSerializer(serializers.Serializer):
|
||||
initial_field = fields.IntegerField(initial=123)
|
||||
blank_field = fields.IntegerField()
|
||||
initial_field = serializers.IntegerField(initial=123)
|
||||
blank_field = serializers.IntegerField()
|
||||
self.serializer = TestSerializer()
|
||||
|
||||
def test_initial(self):
|
||||
|
@ -163,7 +163,7 @@ class TestInitial:
|
|||
class TestLabel:
|
||||
def setup(self):
|
||||
class TestSerializer(serializers.Serializer):
|
||||
labeled = fields.IntegerField(label='My label')
|
||||
labeled = serializers.IntegerField(label='My label')
|
||||
self.serializer = TestSerializer()
|
||||
|
||||
def test_label(self):
|
||||
|
@ -189,7 +189,7 @@ class TestInvalidErrorKey:
|
|||
with pytest.raises(AssertionError) as exc_info:
|
||||
self.field.to_native(123)
|
||||
expected = (
|
||||
'ValidationFailed raised by `ExampleField`, but error key '
|
||||
'ValidationError raised by `ExampleField`, but error key '
|
||||
'`incorrect` does not exist in the `error_messages` dictionary.'
|
||||
)
|
||||
assert str(exc_info.value) == expected
|
||||
|
@ -198,7 +198,7 @@ class TestInvalidErrorKey:
|
|||
class TestBooleanHTMLInput:
|
||||
def setup(self):
|
||||
class TestSerializer(serializers.Serializer):
|
||||
archived = fields.BooleanField()
|
||||
archived = serializers.BooleanField()
|
||||
self.Serializer = TestSerializer
|
||||
|
||||
def test_empty_html_checkbox(self):
|
||||
|
@ -243,7 +243,7 @@ class FieldValues:
|
|||
Ensure that invalid values raise the expected validation error.
|
||||
"""
|
||||
for input_value, expected_failure in get_items(self.invalid_inputs):
|
||||
with pytest.raises(exceptions.ValidationFailed) as exc_info:
|
||||
with pytest.raises(serializers.ValidationError) as exc_info:
|
||||
self.field.run_validation(input_value)
|
||||
assert exc_info.value.detail == expected_failure
|
||||
|
||||
|
@ -283,7 +283,7 @@ class TestBooleanField(FieldValues):
|
|||
False: False,
|
||||
'other': True
|
||||
}
|
||||
field = fields.BooleanField()
|
||||
field = serializers.BooleanField()
|
||||
|
||||
|
||||
class TestNullBooleanField(FieldValues):
|
||||
|
@ -310,7 +310,7 @@ class TestNullBooleanField(FieldValues):
|
|||
None: None,
|
||||
'other': True
|
||||
}
|
||||
field = fields.NullBooleanField()
|
||||
field = serializers.NullBooleanField()
|
||||
|
||||
|
||||
# String types...
|
||||
|
@ -330,7 +330,7 @@ class TestCharField(FieldValues):
|
|||
1: '1',
|
||||
'abc': 'abc'
|
||||
}
|
||||
field = fields.CharField()
|
||||
field = serializers.CharField()
|
||||
|
||||
|
||||
class TestEmailField(FieldValues):
|
||||
|
@ -345,7 +345,7 @@ class TestEmailField(FieldValues):
|
|||
'examplecom': ['Enter a valid email address.']
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.EmailField()
|
||||
field = serializers.EmailField()
|
||||
|
||||
|
||||
class TestRegexField(FieldValues):
|
||||
|
@ -359,7 +359,7 @@ class TestRegexField(FieldValues):
|
|||
'A9': ["This value does not match the required pattern."]
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.RegexField(regex='[a-z][0-9]')
|
||||
field = serializers.RegexField(regex='[a-z][0-9]')
|
||||
|
||||
|
||||
class TestSlugField(FieldValues):
|
||||
|
@ -373,7 +373,7 @@ class TestSlugField(FieldValues):
|
|||
'slug 99': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.SlugField()
|
||||
field = serializers.SlugField()
|
||||
|
||||
|
||||
class TestURLField(FieldValues):
|
||||
|
@ -387,7 +387,7 @@ class TestURLField(FieldValues):
|
|||
'example.com': ['Enter a valid URL.']
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.URLField()
|
||||
field = serializers.URLField()
|
||||
|
||||
|
||||
# Number types...
|
||||
|
@ -415,7 +415,7 @@ class TestIntegerField(FieldValues):
|
|||
1.0: 1,
|
||||
0.0: 0
|
||||
}
|
||||
field = fields.IntegerField()
|
||||
field = serializers.IntegerField()
|
||||
|
||||
|
||||
class TestMinMaxIntegerField(FieldValues):
|
||||
|
@ -435,7 +435,7 @@ class TestMinMaxIntegerField(FieldValues):
|
|||
'4': ['Ensure this value is less than or equal to 3.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.IntegerField(min_value=1, max_value=3)
|
||||
field = serializers.IntegerField(min_value=1, max_value=3)
|
||||
|
||||
|
||||
class TestFloatField(FieldValues):
|
||||
|
@ -461,7 +461,7 @@ class TestFloatField(FieldValues):
|
|||
1.0: 1.0,
|
||||
0.0: 0.0,
|
||||
}
|
||||
field = fields.FloatField()
|
||||
field = serializers.FloatField()
|
||||
|
||||
|
||||
class TestMinMaxFloatField(FieldValues):
|
||||
|
@ -483,7 +483,7 @@ class TestMinMaxFloatField(FieldValues):
|
|||
'3.1': ['Ensure this value is less than or equal to 3.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.FloatField(min_value=1, max_value=3)
|
||||
field = serializers.FloatField(min_value=1, max_value=3)
|
||||
|
||||
|
||||
class TestDecimalField(FieldValues):
|
||||
|
@ -518,7 +518,7 @@ class TestDecimalField(FieldValues):
|
|||
Decimal('1.09'): '1.1',
|
||||
Decimal('0.04'): '0.0'
|
||||
}
|
||||
field = fields.DecimalField(max_digits=3, decimal_places=1)
|
||||
field = serializers.DecimalField(max_digits=3, decimal_places=1)
|
||||
|
||||
|
||||
class TestMinMaxDecimalField(FieldValues):
|
||||
|
@ -534,7 +534,7 @@ class TestMinMaxDecimalField(FieldValues):
|
|||
'20.1': ['Ensure this value is less than or equal to 20.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.DecimalField(
|
||||
field = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=1,
|
||||
min_value=10, max_value=20
|
||||
)
|
||||
|
@ -554,13 +554,13 @@ class TestNoStringCoercionDecimalField(FieldValues):
|
|||
Decimal('1.09'): Decimal('1.1'),
|
||||
Decimal('0.04'): Decimal('0.0'),
|
||||
}
|
||||
field = fields.DecimalField(
|
||||
field = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=1,
|
||||
coerce_to_string=False
|
||||
)
|
||||
|
||||
|
||||
# Date & time fields...
|
||||
# Date & time serializers...
|
||||
|
||||
class TestDateField(FieldValues):
|
||||
"""
|
||||
|
@ -578,7 +578,7 @@ class TestDateField(FieldValues):
|
|||
outputs = {
|
||||
datetime.date(2001, 1, 1): '2001-01-01'
|
||||
}
|
||||
field = fields.DateField()
|
||||
field = serializers.DateField()
|
||||
|
||||
|
||||
class TestCustomInputFormatDateField(FieldValues):
|
||||
|
@ -592,7 +592,7 @@ class TestCustomInputFormatDateField(FieldValues):
|
|||
'2001-01-01': ['Date has wrong format. Use one of these formats instead: DD [Jan-Dec] YYYY']
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.DateField(input_formats=['%d %b %Y'])
|
||||
field = serializers.DateField(input_formats=['%d %b %Y'])
|
||||
|
||||
|
||||
class TestCustomOutputFormatDateField(FieldValues):
|
||||
|
@ -604,7 +604,7 @@ class TestCustomOutputFormatDateField(FieldValues):
|
|||
outputs = {
|
||||
datetime.date(2001, 1, 1): '01 Jan 2001'
|
||||
}
|
||||
field = fields.DateField(format='%d %b %Y')
|
||||
field = serializers.DateField(format='%d %b %Y')
|
||||
|
||||
|
||||
class TestNoOutputFormatDateField(FieldValues):
|
||||
|
@ -616,7 +616,7 @@ class TestNoOutputFormatDateField(FieldValues):
|
|||
outputs = {
|
||||
datetime.date(2001, 1, 1): datetime.date(2001, 1, 1)
|
||||
}
|
||||
field = fields.DateField(format=None)
|
||||
field = serializers.DateField(format=None)
|
||||
|
||||
|
||||
class TestDateTimeField(FieldValues):
|
||||
|
@ -641,7 +641,7 @@ class TestDateTimeField(FieldValues):
|
|||
datetime.datetime(2001, 1, 1, 13, 00): '2001-01-01T13:00:00',
|
||||
datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): '2001-01-01T13:00:00Z'
|
||||
}
|
||||
field = fields.DateTimeField(default_timezone=timezone.UTC())
|
||||
field = serializers.DateTimeField(default_timezone=timezone.UTC())
|
||||
|
||||
|
||||
class TestCustomInputFormatDateTimeField(FieldValues):
|
||||
|
@ -655,7 +655,7 @@ class TestCustomInputFormatDateTimeField(FieldValues):
|
|||
'2001-01-01T20:50': ['Datetime has wrong format. Use one of these formats instead: hh:mm[AM|PM], DD [Jan-Dec] YYYY']
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.DateTimeField(default_timezone=timezone.UTC(), input_formats=['%I:%M%p, %d %b %Y'])
|
||||
field = serializers.DateTimeField(default_timezone=timezone.UTC(), input_formats=['%I:%M%p, %d %b %Y'])
|
||||
|
||||
|
||||
class TestCustomOutputFormatDateTimeField(FieldValues):
|
||||
|
@ -667,7 +667,7 @@ class TestCustomOutputFormatDateTimeField(FieldValues):
|
|||
outputs = {
|
||||
datetime.datetime(2001, 1, 1, 13, 00): '01:00PM, 01 Jan 2001',
|
||||
}
|
||||
field = fields.DateTimeField(format='%I:%M%p, %d %b %Y')
|
||||
field = serializers.DateTimeField(format='%I:%M%p, %d %b %Y')
|
||||
|
||||
|
||||
class TestNoOutputFormatDateTimeField(FieldValues):
|
||||
|
@ -679,7 +679,7 @@ class TestNoOutputFormatDateTimeField(FieldValues):
|
|||
outputs = {
|
||||
datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1, 13, 00),
|
||||
}
|
||||
field = fields.DateTimeField(format=None)
|
||||
field = serializers.DateTimeField(format=None)
|
||||
|
||||
|
||||
class TestNaiveDateTimeField(FieldValues):
|
||||
|
@ -692,7 +692,7 @@ class TestNaiveDateTimeField(FieldValues):
|
|||
}
|
||||
invalid_inputs = {}
|
||||
outputs = {}
|
||||
field = fields.DateTimeField(default_timezone=None)
|
||||
field = serializers.DateTimeField(default_timezone=None)
|
||||
|
||||
|
||||
class TestTimeField(FieldValues):
|
||||
|
@ -710,7 +710,7 @@ class TestTimeField(FieldValues):
|
|||
outputs = {
|
||||
datetime.time(13, 00): '13:00:00'
|
||||
}
|
||||
field = fields.TimeField()
|
||||
field = serializers.TimeField()
|
||||
|
||||
|
||||
class TestCustomInputFormatTimeField(FieldValues):
|
||||
|
@ -724,7 +724,7 @@ class TestCustomInputFormatTimeField(FieldValues):
|
|||
'13:00': ['Time has wrong format. Use one of these formats instead: hh:mm[AM|PM]'],
|
||||
}
|
||||
outputs = {}
|
||||
field = fields.TimeField(input_formats=['%I:%M%p'])
|
||||
field = serializers.TimeField(input_formats=['%I:%M%p'])
|
||||
|
||||
|
||||
class TestCustomOutputFormatTimeField(FieldValues):
|
||||
|
@ -736,7 +736,7 @@ class TestCustomOutputFormatTimeField(FieldValues):
|
|||
outputs = {
|
||||
datetime.time(13, 00): '01:00PM'
|
||||
}
|
||||
field = fields.TimeField(format='%I:%M%p')
|
||||
field = serializers.TimeField(format='%I:%M%p')
|
||||
|
||||
|
||||
class TestNoOutputFormatTimeField(FieldValues):
|
||||
|
@ -748,7 +748,7 @@ class TestNoOutputFormatTimeField(FieldValues):
|
|||
outputs = {
|
||||
datetime.time(13, 00): datetime.time(13, 00)
|
||||
}
|
||||
field = fields.TimeField(format=None)
|
||||
field = serializers.TimeField(format=None)
|
||||
|
||||
|
||||
# Choice types...
|
||||
|
@ -768,7 +768,7 @@ class TestChoiceField(FieldValues):
|
|||
outputs = {
|
||||
'good': 'good'
|
||||
}
|
||||
field = fields.ChoiceField(
|
||||
field = serializers.ChoiceField(
|
||||
choices=[
|
||||
('poor', 'Poor quality'),
|
||||
('medium', 'Medium quality'),
|
||||
|
@ -794,7 +794,7 @@ class TestChoiceFieldWithType(FieldValues):
|
|||
'1': 1,
|
||||
1: 1
|
||||
}
|
||||
field = fields.ChoiceField(
|
||||
field = serializers.ChoiceField(
|
||||
choices=[
|
||||
(1, 'Poor quality'),
|
||||
(2, 'Medium quality'),
|
||||
|
@ -819,7 +819,7 @@ class TestChoiceFieldWithListChoices(FieldValues):
|
|||
outputs = {
|
||||
'good': 'good'
|
||||
}
|
||||
field = fields.ChoiceField(choices=('poor', 'medium', 'good'))
|
||||
field = serializers.ChoiceField(choices=('poor', 'medium', 'good'))
|
||||
|
||||
|
||||
class TestMultipleChoiceField(FieldValues):
|
||||
|
@ -838,7 +838,7 @@ class TestMultipleChoiceField(FieldValues):
|
|||
outputs = [
|
||||
(['aircon', 'manual'], set(['aircon', 'manual']))
|
||||
]
|
||||
field = fields.MultipleChoiceField(
|
||||
field = serializers.MultipleChoiceField(
|
||||
choices=[
|
||||
('aircon', 'AirCon'),
|
||||
('manual', 'Manual drive'),
|
||||
|
@ -847,7 +847,7 @@ class TestMultipleChoiceField(FieldValues):
|
|||
)
|
||||
|
||||
|
||||
# File fields...
|
||||
# File serializers...
|
||||
|
||||
class MockFile:
|
||||
def __init__(self, name='', size=0, url=''):
|
||||
|
@ -881,7 +881,7 @@ class TestFileField(FieldValues):
|
|||
(MockFile(name='example.txt', url='/example.txt'), '/example.txt'),
|
||||
('', None)
|
||||
]
|
||||
field = fields.FileField(max_length=10)
|
||||
field = serializers.FileField(max_length=10)
|
||||
|
||||
|
||||
class TestFieldFieldWithName(FieldValues):
|
||||
|
@ -893,14 +893,14 @@ class TestFieldFieldWithName(FieldValues):
|
|||
outputs = [
|
||||
(MockFile(name='example.txt', url='/example.txt'), 'example.txt')
|
||||
]
|
||||
field = fields.FileField(use_url=False)
|
||||
field = serializers.FileField(use_url=False)
|
||||
|
||||
|
||||
# Stub out mock Django `forms.ImageField` class so we don't *actually*
|
||||
# call into it's regular validation, or require PIL for testing.
|
||||
class FailImageValidation(object):
|
||||
def to_python(self, value):
|
||||
raise exceptions.ValidationFailed(self.error_messages['invalid_image'])
|
||||
raise serializers.ValidationError(self.error_messages['invalid_image'])
|
||||
|
||||
|
||||
class PassImageValidation(object):
|
||||
|
@ -917,7 +917,7 @@ class TestInvalidImageField(FieldValues):
|
|||
(MockFile(name='example.txt', size=10), ['Upload a valid image. The file you uploaded was either not an image or a corrupted image.'])
|
||||
]
|
||||
outputs = {}
|
||||
field = fields.ImageField(_DjangoImageField=FailImageValidation)
|
||||
field = serializers.ImageField(_DjangoImageField=FailImageValidation)
|
||||
|
||||
|
||||
class TestValidImageField(FieldValues):
|
||||
|
@ -929,10 +929,10 @@ class TestValidImageField(FieldValues):
|
|||
]
|
||||
invalid_inputs = {}
|
||||
outputs = {}
|
||||
field = fields.ImageField(_DjangoImageField=PassImageValidation)
|
||||
field = serializers.ImageField(_DjangoImageField=PassImageValidation)
|
||||
|
||||
|
||||
# Composite fields...
|
||||
# Composite serializers...
|
||||
|
||||
class TestListField(FieldValues):
|
||||
"""
|
||||
|
@ -950,7 +950,7 @@ class TestListField(FieldValues):
|
|||
([1, 2, 3], [1, 2, 3]),
|
||||
(['1', '2', '3'], [1, 2, 3])
|
||||
]
|
||||
field = fields.ListField(child=fields.IntegerField())
|
||||
field = serializers.ListField(child=serializers.IntegerField())
|
||||
|
||||
|
||||
# Tests for FieldField.
|
||||
|
@ -963,7 +963,7 @@ class MockRequest:
|
|||
|
||||
class TestFileFieldContext:
|
||||
def test_fully_qualified_when_request_in_context(self):
|
||||
field = fields.FileField(max_length=10)
|
||||
field = serializers.FileField(max_length=10)
|
||||
field._context = {'request': MockRequest()}
|
||||
obj = MockFile(name='example.txt', url='/example.txt')
|
||||
value = field.to_representation(obj)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from .utils import mock_reverse, fail_reverse, BadType, MockObject, MockQueryset
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from rest_framework import exceptions, serializers
|
||||
from rest_framework import serializers
|
||||
from rest_framework.test import APISimpleTestCase
|
||||
import pytest
|
||||
|
||||
|
@ -30,13 +30,13 @@ class TestPrimaryKeyRelatedField(APISimpleTestCase):
|
|||
assert instance is self.instance
|
||||
|
||||
def test_pk_related_lookup_does_not_exist(self):
|
||||
with pytest.raises(exceptions.ValidationFailed) as excinfo:
|
||||
with pytest.raises(serializers.ValidationError) as excinfo:
|
||||
self.field.to_internal_value(4)
|
||||
msg = excinfo.value.detail[0]
|
||||
assert msg == "Invalid pk '4' - object does not exist."
|
||||
|
||||
def test_pk_related_lookup_invalid_type(self):
|
||||
with pytest.raises(exceptions.ValidationFailed) as excinfo:
|
||||
with pytest.raises(serializers.ValidationError) as excinfo:
|
||||
self.field.to_internal_value(BadType())
|
||||
msg = excinfo.value.detail[0]
|
||||
assert msg == 'Incorrect type. Expected pk value, received BadType.'
|
||||
|
@ -120,13 +120,13 @@ class TestSlugRelatedField(APISimpleTestCase):
|
|||
assert instance is self.instance
|
||||
|
||||
def test_slug_related_lookup_does_not_exist(self):
|
||||
with pytest.raises(exceptions.ValidationFailed) as excinfo:
|
||||
with pytest.raises(serializers.ValidationError) as excinfo:
|
||||
self.field.to_internal_value('doesnotexist')
|
||||
msg = excinfo.value.detail[0]
|
||||
assert msg == 'Object with name=doesnotexist does not exist.'
|
||||
|
||||
def test_slug_related_lookup_invalid_type(self):
|
||||
with pytest.raises(exceptions.ValidationFailed) as excinfo:
|
||||
with pytest.raises(serializers.ValidationError) as excinfo:
|
||||
self.field.to_internal_value(BadType())
|
||||
msg = excinfo.value.detail[0]
|
||||
assert msg == 'Invalid value.'
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||
from django.core.validators import MaxValueValidator
|
||||
from django.db import models
|
||||
from django.test import TestCase
|
||||
from rest_framework import exceptions, generics, serializers, status
|
||||
from rest_framework import generics, serializers, status
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
factory = APIRequestFactory()
|
||||
|
@ -37,7 +37,7 @@ class ShouldValidateModelSerializer(serializers.ModelSerializer):
|
|||
|
||||
def validate_renamed(self, value):
|
||||
if len(value) < 3:
|
||||
raise exceptions.ValidationFailed('Minimum 3 characters.')
|
||||
raise serializers.ValidationError('Minimum 3 characters.')
|
||||
return value
|
||||
|
||||
class Meta:
|
||||
|
@ -73,10 +73,10 @@ class ValidationSerializer(serializers.Serializer):
|
|||
foo = serializers.CharField()
|
||||
|
||||
def validate_foo(self, attrs, source):
|
||||
raise exceptions.ValidationFailed("foo invalid")
|
||||
raise serializers.ValidationError("foo invalid")
|
||||
|
||||
def validate(self, attrs):
|
||||
raise exceptions.ValidationFailed("serializer invalid")
|
||||
raise serializers.ValidationError("serializer invalid")
|
||||
|
||||
|
||||
class TestAvoidValidation(TestCase):
|
||||
|
@ -158,7 +158,7 @@ class TestChoiceFieldChoicesValidate(TestCase):
|
|||
value = self.CHOICES[0][0]
|
||||
try:
|
||||
f.to_internal_value(value)
|
||||
except exceptions.ValidationFailed:
|
||||
except serializers.ValidationError:
|
||||
self.fail("Value %s does not validate" % str(value))
|
||||
|
||||
# def test_nested_choices(self):
|
||||
|
|
Loading…
Reference in New Issue
Block a user