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