mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-06 05:20:12 +03:00
Update default error messages for translations
Make use of already translated strings in Django, wherever possible and makes sense.
This commit is contained in:
parent
6d8a652ef6
commit
f076caebb0
|
@ -491,7 +491,7 @@ As an example, let's create a field that can be used represent the class name of
|
||||||
# We pass the object instance onto `to_representation`,
|
# We pass the object instance onto `to_representation`,
|
||||||
# not just the field attribute.
|
# not just the field attribute.
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def to_representation(self, obj):
|
def to_representation(self, obj):
|
||||||
"""
|
"""
|
||||||
Serialize the object's class name.
|
Serialize the object's class name.
|
||||||
|
@ -522,7 +522,7 @@ To indicate invalid data, we should raise a `serializers.ValidationError`, like
|
||||||
The `.fail()` method is a shortcut for raising `ValidationError` that takes a message string from the `error_messages` dictionary. For example:
|
The `.fail()` method is a shortcut for raising `ValidationError` that takes a message string from the `error_messages` dictionary. For example:
|
||||||
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}',
|
'incorrect_type': 'Incorrect type. Expected a string, but got %(input_type)s',
|
||||||
'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
|
'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
|
||||||
'out_of_range': 'Value out of range. Must be between 0 and 255.'
|
'out_of_range': 'Value out of range. Must be between 0 and 255.'
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.forms import ImageField as DjangoImageField
|
||||||
from django.utils import six, timezone
|
from django.utils import six, timezone
|
||||||
from django.utils.dateparse import parse_date, parse_datetime, parse_time
|
from django.utils.dateparse import parse_date, parse_datetime, parse_time
|
||||||
from django.utils.encoding import is_protected_type, smart_text
|
from django.utils.encoding import is_protected_type, smart_text
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ungettext_lazy, ugettext_lazy as _
|
||||||
from rest_framework import ISO_8601
|
from rest_framework import ISO_8601
|
||||||
from rest_framework.compat import (
|
from rest_framework.compat import (
|
||||||
EmailValidator, MinValueValidator, MaxValueValidator,
|
EmailValidator, MinValueValidator, MaxValueValidator,
|
||||||
|
@ -147,7 +147,7 @@ class Field(object):
|
||||||
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'required': _('This field is required.'),
|
'required': _('This field is required.'),
|
||||||
'null': _('This field may not be null.')
|
'null': _('This field cannot be null.')
|
||||||
}
|
}
|
||||||
default_validators = []
|
default_validators = []
|
||||||
default_empty_html = empty
|
default_empty_html = empty
|
||||||
|
@ -369,7 +369,7 @@ class Field(object):
|
||||||
class_name = self.__class__.__name__
|
class_name = self.__class__.__name__
|
||||||
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 % kwargs
|
||||||
raise ValidationError(message_string)
|
raise ValidationError(message_string)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -429,7 +429,7 @@ class Field(object):
|
||||||
|
|
||||||
class BooleanField(Field):
|
class BooleanField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('`{input}` is not a valid boolean.')
|
'invalid': _('`%(input)s` is not a valid boolean.')
|
||||||
}
|
}
|
||||||
default_empty_html = False
|
default_empty_html = False
|
||||||
initial = False
|
initial = False
|
||||||
|
@ -457,7 +457,7 @@ class BooleanField(Field):
|
||||||
|
|
||||||
class NullBooleanField(Field):
|
class NullBooleanField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('`{input}` is not a valid boolean.')
|
'invalid': _('`%(input)s` is not a valid boolean.')
|
||||||
}
|
}
|
||||||
initial = None
|
initial = None
|
||||||
TRUE_VALUES = set(('t', 'T', 'true', 'True', 'TRUE', '1', 1, True))
|
TRUE_VALUES = set(('t', 'T', 'true', 'True', 'TRUE', '1', 1, True))
|
||||||
|
@ -492,9 +492,15 @@ class NullBooleanField(Field):
|
||||||
|
|
||||||
class CharField(Field):
|
class CharField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'blank': _('This field may not be blank.'),
|
'blank': _('This field cannot be blank.'),
|
||||||
'max_length': _('Ensure this field has no more than {max_length} characters.'),
|
'max_length': ungettext_lazy(
|
||||||
'min_length': _('Ensure this field has no more than {min_length} characters.')
|
'Ensure this value has at most %(limit_value)d character (it has %(show_value)d).',
|
||||||
|
'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).',
|
||||||
|
'limit_value'),
|
||||||
|
'min_length': ungettext_lazy(
|
||||||
|
'Ensure this value has at least %(limit_value)d character (it has %(show_value)d).',
|
||||||
|
'Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).',
|
||||||
|
'limit_value')
|
||||||
}
|
}
|
||||||
initial = ''
|
initial = ''
|
||||||
coerce_blank_to_null = False
|
coerce_blank_to_null = False
|
||||||
|
@ -502,15 +508,9 @@ class CharField(Field):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.allow_blank = kwargs.pop('allow_blank', False)
|
self.allow_blank = kwargs.pop('allow_blank', False)
|
||||||
max_length = kwargs.pop('max_length', None)
|
self.max_length = kwargs.pop('max_length', None)
|
||||||
min_length = kwargs.pop('min_length', None)
|
self.min_length = kwargs.pop('min_length', None)
|
||||||
super(CharField, self).__init__(**kwargs)
|
super(CharField, self).__init__(**kwargs)
|
||||||
if max_length is not None:
|
|
||||||
message = self.error_messages['max_length'].format(max_length=max_length)
|
|
||||||
self.validators.append(MaxLengthValidator(max_length, message=message))
|
|
||||||
if min_length is not None:
|
|
||||||
message = self.error_messages['min_length'].format(min_length=min_length)
|
|
||||||
self.validators.append(MinLengthValidator(min_length, message=message))
|
|
||||||
|
|
||||||
def run_validation(self, data=empty):
|
def run_validation(self, data=empty):
|
||||||
# Test for the empty string here so that it does not get validated,
|
# Test for the empty string here so that it does not get validated,
|
||||||
|
@ -520,6 +520,17 @@ class CharField(Field):
|
||||||
if not self.allow_blank:
|
if not self.allow_blank:
|
||||||
self.fail('blank')
|
self.fail('blank')
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
if self.max_length is not None:
|
||||||
|
params = {'limit_value': self.max_length, 'show_value': data}
|
||||||
|
message = self.error_messages['max_length'] % params
|
||||||
|
self.validators.append(MaxLengthValidator(self.max_length, message=message))
|
||||||
|
|
||||||
|
if self.min_length is not None:
|
||||||
|
params = {'limit_value': self.min_length, 'show_value': data}
|
||||||
|
message = self.error_messages['min_length'] % params
|
||||||
|
self.validators.append(MinLengthValidator(self.min_length, message=message))
|
||||||
|
|
||||||
return super(CharField, self).run_validation(data)
|
return super(CharField, self).run_validation(data)
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
|
@ -571,7 +582,7 @@ class SlugField(CharField):
|
||||||
|
|
||||||
class URLField(CharField):
|
class URLField(CharField):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _("Enter a valid URL.")
|
'invalid': _('Enter a valid URL.')
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
@ -585,8 +596,8 @@ class URLField(CharField):
|
||||||
class IntegerField(Field):
|
class IntegerField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('A valid integer is required.'),
|
'invalid': _('A valid integer is required.'),
|
||||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'),
|
||||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'),
|
||||||
'max_string_length': _('String value too large')
|
'max_string_length': _('String value too large')
|
||||||
}
|
}
|
||||||
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
||||||
|
@ -596,10 +607,10 @@ class IntegerField(Field):
|
||||||
min_value = kwargs.pop('min_value', None)
|
min_value = kwargs.pop('min_value', None)
|
||||||
super(IntegerField, self).__init__(**kwargs)
|
super(IntegerField, self).__init__(**kwargs)
|
||||||
if max_value is not None:
|
if max_value is not None:
|
||||||
message = self.error_messages['max_value'].format(max_value=max_value)
|
message = self.error_messages['max_value'] % {'limit_value': max_value}
|
||||||
self.validators.append(MaxValueValidator(max_value, message=message))
|
self.validators.append(MaxValueValidator(max_value, message=message))
|
||||||
if min_value is not None:
|
if min_value is not None:
|
||||||
message = self.error_messages['min_value'].format(min_value=min_value)
|
message = self.error_messages['min_value'] % {'limit_value': min_value}
|
||||||
self.validators.append(MinValueValidator(min_value, message=message))
|
self.validators.append(MinValueValidator(min_value, message=message))
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
|
@ -618,9 +629,9 @@ class IntegerField(Field):
|
||||||
|
|
||||||
class FloatField(Field):
|
class FloatField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _("A valid number is required."),
|
'invalid': _('A valid number is required.'),
|
||||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'),
|
||||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'),
|
||||||
'max_string_length': _('String value too large')
|
'max_string_length': _('String value too large')
|
||||||
}
|
}
|
||||||
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
||||||
|
@ -630,10 +641,12 @@ class FloatField(Field):
|
||||||
min_value = kwargs.pop('min_value', None)
|
min_value = kwargs.pop('min_value', None)
|
||||||
super(FloatField, self).__init__(**kwargs)
|
super(FloatField, self).__init__(**kwargs)
|
||||||
if max_value is not None:
|
if max_value is not None:
|
||||||
message = self.error_messages['max_value'].format(max_value=max_value)
|
params = {'limit_value': max_value}
|
||||||
|
message = self.error_messages['max_value'] % params
|
||||||
self.validators.append(MaxValueValidator(max_value, message=message))
|
self.validators.append(MaxValueValidator(max_value, message=message))
|
||||||
if min_value is not None:
|
if min_value is not None:
|
||||||
message = self.error_messages['min_value'].format(min_value=min_value)
|
params = {'limit_value': min_value}
|
||||||
|
message = self.error_messages['min_value'] % params
|
||||||
self.validators.append(MinValueValidator(min_value, message=message))
|
self.validators.append(MinValueValidator(min_value, message=message))
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
|
@ -652,11 +665,20 @@ class FloatField(Field):
|
||||||
class DecimalField(Field):
|
class DecimalField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('A valid number is required.'),
|
'invalid': _('A valid number is required.'),
|
||||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'),
|
||||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'),
|
||||||
'max_digits': _('Ensure that there are no more than {max_digits} digits in total.'),
|
'max_digits': ungettext_lazy(
|
||||||
'max_decimal_places': _('Ensure that there are no more than {max_decimal_places} decimal places.'),
|
'Ensure that there are no more than %(max)s digit in total.',
|
||||||
'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.'),
|
'Ensure that there are no more than %(max)s digits in total.',
|
||||||
|
'max'),
|
||||||
|
'max_decimal_places': ungettext_lazy(
|
||||||
|
'Ensure that there are no more than %(max)s decimal place.',
|
||||||
|
'Ensure that there are no more than %(max)s decimal places.',
|
||||||
|
'max'),
|
||||||
|
'max_whole_digits': ungettext_lazy(
|
||||||
|
'Ensure that there are no more than %(max)s digit before the decimal point.',
|
||||||
|
'Ensure that there are no more than %(max)s digits before the decimal point.',
|
||||||
|
'max'),
|
||||||
'max_string_length': _('String value too large')
|
'max_string_length': _('String value too large')
|
||||||
}
|
}
|
||||||
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
||||||
|
@ -669,10 +691,12 @@ class DecimalField(Field):
|
||||||
self.coerce_to_string = coerce_to_string if (coerce_to_string is not None) else self.coerce_to_string
|
self.coerce_to_string = coerce_to_string if (coerce_to_string is not None) else self.coerce_to_string
|
||||||
super(DecimalField, self).__init__(**kwargs)
|
super(DecimalField, self).__init__(**kwargs)
|
||||||
if max_value is not None:
|
if max_value is not None:
|
||||||
message = self.error_messages['max_value'].format(max_value=max_value)
|
params = {'limit_value': max_value}
|
||||||
|
message = self.error_messages['max_value'] % params
|
||||||
self.validators.append(MaxValueValidator(max_value, message=message))
|
self.validators.append(MaxValueValidator(max_value, message=message))
|
||||||
if min_value is not None:
|
if min_value is not None:
|
||||||
message = self.error_messages['min_value'].format(min_value=min_value)
|
params = {'limit_value': min_value}
|
||||||
|
message = self.error_messages['min_value'] % params
|
||||||
self.validators.append(MinValueValidator(min_value, message=message))
|
self.validators.append(MinValueValidator(min_value, message=message))
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
|
@ -713,11 +737,11 @@ class DecimalField(Field):
|
||||||
whole_digits = digits - decimals
|
whole_digits = digits - decimals
|
||||||
|
|
||||||
if self.max_digits is not None and digits > self.max_digits:
|
if self.max_digits is not None and digits > self.max_digits:
|
||||||
self.fail('max_digits', max_digits=self.max_digits)
|
self.fail('max_digits', max=self.max_digits)
|
||||||
if self.decimal_places is not None and decimals > self.decimal_places:
|
if self.decimal_places is not None and decimals > self.decimal_places:
|
||||||
self.fail('max_decimal_places', max_decimal_places=self.decimal_places)
|
self.fail('max_decimal_places', max=self.decimal_places)
|
||||||
if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
|
if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
|
||||||
self.fail('max_whole_digits', max_whole_digits=self.max_digits - self.decimal_places)
|
self.fail('max_whole_digits', max=self.max_digits - self.decimal_places)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -740,7 +764,7 @@ class DecimalField(Field):
|
||||||
|
|
||||||
class DateTimeField(Field):
|
class DateTimeField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}'),
|
'invalid': _('Datetime has wrong format. Use one of these formats instead: %(format)s'),
|
||||||
'date': _('Expected a datetime but got a date.'),
|
'date': _('Expected a datetime but got a date.'),
|
||||||
}
|
}
|
||||||
format = api_settings.DATETIME_FORMAT
|
format = api_settings.DATETIME_FORMAT
|
||||||
|
@ -805,7 +829,7 @@ class DateTimeField(Field):
|
||||||
|
|
||||||
class DateField(Field):
|
class DateField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('Date has wrong format. Use one of these formats instead: {format}'),
|
'invalid': _('Date has wrong format. Use one of these formats instead: %(format)s'),
|
||||||
'datetime': _('Expected a date but got a datetime.'),
|
'datetime': _('Expected a date but got a datetime.'),
|
||||||
}
|
}
|
||||||
format = api_settings.DATE_FORMAT
|
format = api_settings.DATE_FORMAT
|
||||||
|
@ -863,7 +887,7 @@ class DateField(Field):
|
||||||
|
|
||||||
class TimeField(Field):
|
class TimeField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('Time has wrong format. Use one of these formats instead: {format}'),
|
'invalid': _('Time has wrong format. Use one of these formats instead: %(format)s'),
|
||||||
}
|
}
|
||||||
format = api_settings.TIME_FORMAT
|
format = api_settings.TIME_FORMAT
|
||||||
input_formats = api_settings.TIME_INPUT_FORMATS
|
input_formats = api_settings.TIME_INPUT_FORMATS
|
||||||
|
@ -919,7 +943,7 @@ class TimeField(Field):
|
||||||
|
|
||||||
class ChoiceField(Field):
|
class ChoiceField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid_choice': _('`{input}` is not a valid choice.')
|
'invalid_choice': _('Value %(value)r is not a valid choice.')
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, choices, **kwargs):
|
def __init__(self, choices, **kwargs):
|
||||||
|
@ -948,7 +972,7 @@ class ChoiceField(Field):
|
||||||
try:
|
try:
|
||||||
return self.choice_strings_to_values[six.text_type(data)]
|
return self.choice_strings_to_values[six.text_type(data)]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.fail('invalid_choice', input=data)
|
self.fail('invalid_choice', value=data)
|
||||||
|
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
if value in ('', None):
|
if value in ('', None):
|
||||||
|
@ -958,8 +982,8 @@ class ChoiceField(Field):
|
||||||
|
|
||||||
class MultipleChoiceField(ChoiceField):
|
class MultipleChoiceField(ChoiceField):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid_choice': _('`{input}` is not a valid choice.'),
|
'invalid_choice': _('Value %(value)r is not a valid choice.'),
|
||||||
'not_a_list': _('Expected a list of items but got type `{input_type}`.')
|
'not_a_list': _('Expected a list of items but got type `%(input_type)s`.')
|
||||||
}
|
}
|
||||||
default_empty_html = []
|
default_empty_html = []
|
||||||
|
|
||||||
|
@ -989,11 +1013,14 @@ class MultipleChoiceField(ChoiceField):
|
||||||
|
|
||||||
class FileField(Field):
|
class FileField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'required': _("No file was submitted."),
|
'required': _('No file was submitted.'),
|
||||||
'invalid': _("The submitted data was not a file. Check the encoding type on the form."),
|
'invalid': _('The submitted data was not a file. Check the encoding type on the form.'),
|
||||||
'no_name': _("No filename could be determined."),
|
'no_name': _('No filename could be determined.'),
|
||||||
'empty': _("The submitted file is empty."),
|
'empty': _('The submitted file is empty.'),
|
||||||
'max_length': _('Ensure this filename has at most {max_length} characters (it has {length}).'),
|
'max_length': ungettext_lazy(
|
||||||
|
'Ensure this filename has at most %(max)d character (it has %(length)d).',
|
||||||
|
'Ensure this filename has at most %(max)d characters (it has %(length)d).',
|
||||||
|
'max'),
|
||||||
}
|
}
|
||||||
use_url = api_settings.UPLOADED_FILES_USE_URL
|
use_url = api_settings.UPLOADED_FILES_USE_URL
|
||||||
|
|
||||||
|
@ -1016,7 +1043,7 @@ class FileField(Field):
|
||||||
if not self.allow_empty_file and not file_size:
|
if not self.allow_empty_file and not file_size:
|
||||||
self.fail('empty')
|
self.fail('empty')
|
||||||
if self.max_length and len(file_name) > self.max_length:
|
if self.max_length and len(file_name) > self.max_length:
|
||||||
self.fail('max_length', max_length=self.max_length, length=len(file_name))
|
self.fail('max_length', max=self.max_length, length=len(file_name))
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -1061,7 +1088,7 @@ class ListField(Field):
|
||||||
child = None
|
child = None
|
||||||
initial = []
|
initial = []
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'not_a_list': _('Expected a list of items but got type `{input_type}`')
|
'not_a_list': _('Expected a list of items but got type `%(input_type)s`')
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -1192,18 +1219,26 @@ class ModelField(Field):
|
||||||
that do not have a serializer field to be mapped to.
|
that do not have a serializer field to be mapped to.
|
||||||
"""
|
"""
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'max_length': _('Ensure this field has no more than {max_length} characters.'),
|
'max_length': ungettext_lazy(
|
||||||
|
'Ensure this value has at most %(limit_value)d character (it has %(show_value)d).',
|
||||||
|
'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).',
|
||||||
|
'limit_value'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, model_field, **kwargs):
|
def __init__(self, model_field, **kwargs):
|
||||||
self.model_field = model_field
|
self.model_field = model_field
|
||||||
# The `max_length` option is supported by Django's base `Field` class,
|
# The `max_length` option is supported by Django's base `Field` class,
|
||||||
# so we'd better support it here.
|
# so we'd better support it here.
|
||||||
max_length = kwargs.pop('max_length', None)
|
self.max_length = kwargs.pop('max_length', None)
|
||||||
super(ModelField, self).__init__(**kwargs)
|
super(ModelField, self).__init__(**kwargs)
|
||||||
if max_length is not None:
|
|
||||||
message = self.error_messages['max_length'].format(max_length=max_length)
|
def run_validation(self, data=empty):
|
||||||
self.validators.append(MaxLengthValidator(max_length, message=message))
|
if self.max_length is not None:
|
||||||
|
params = {'limit_value': self.max_length, 'show_value': data}
|
||||||
|
message = self.error_messages['max_length'] % params
|
||||||
|
self.validators.append(MaxLengthValidator(self.max_length, message=message))
|
||||||
|
|
||||||
|
return super(ModelField, self).run_validation(data)
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
rel = getattr(self.model_field, 'rel', None)
|
rel = getattr(self.model_field, 'rel', None)
|
||||||
|
|
|
@ -116,8 +116,8 @@ class StringRelatedField(RelatedField):
|
||||||
class PrimaryKeyRelatedField(RelatedField):
|
class PrimaryKeyRelatedField(RelatedField):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'required': 'This field is required.',
|
'required': 'This field is required.',
|
||||||
'does_not_exist': "Invalid pk '{pk_value}' - object does not exist.",
|
'does_not_exist': "Invalid pk '%(pk_value)s' - object does not exist.",
|
||||||
'incorrect_type': 'Incorrect type. Expected pk value, received {data_type}.',
|
'incorrect_type': 'Incorrect type. Expected pk value, received %(data_type)s.',
|
||||||
}
|
}
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
|
@ -166,7 +166,7 @@ class HyperlinkedRelatedField(RelatedField):
|
||||||
'no_match': 'Invalid hyperlink - No URL match',
|
'no_match': 'Invalid hyperlink - No URL match',
|
||||||
'incorrect_match': 'Invalid hyperlink - Incorrect URL match.',
|
'incorrect_match': 'Invalid hyperlink - Incorrect URL match.',
|
||||||
'does_not_exist': 'Invalid hyperlink - Object does not exist.',
|
'does_not_exist': 'Invalid hyperlink - Object does not exist.',
|
||||||
'incorrect_type': 'Incorrect type. Expected URL string, received {data_type}.',
|
'incorrect_type': 'Incorrect type. Expected URL string, received %(data_type)s.',
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, view_name=None, **kwargs):
|
def __init__(self, view_name=None, **kwargs):
|
||||||
|
@ -293,7 +293,7 @@ class SlugRelatedField(RelatedField):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'does_not_exist': _("Object with {slug_name}={value} does not exist."),
|
'does_not_exist': _("Object with %(slug_name)s=%(value)s does not exist."),
|
||||||
'invalid': _('Invalid value.'),
|
'invalid': _('Invalid value.'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class TestSimpleBoundField:
|
||||||
serializer.is_valid()
|
serializer.is_valid()
|
||||||
|
|
||||||
assert serializer['text'].value == 'x' * 1000
|
assert serializer['text'].value == 'x' * 1000
|
||||||
assert serializer['text'].errors == ['Ensure this field has no more than 100 characters.']
|
assert serializer['text'].errors == ['Ensure this value has at most 100 characters (it has 1000).']
|
||||||
assert serializer['text'].name == 'text'
|
assert serializer['text'].name == 'text'
|
||||||
assert serializer['amount'].value is 123
|
assert serializer['amount'].value is 123
|
||||||
assert serializer['amount'].errors is None
|
assert serializer['amount'].errors is None
|
||||||
|
|
|
@ -49,7 +49,7 @@ class TestEmpty:
|
||||||
field = serializers.IntegerField()
|
field = serializers.IntegerField()
|
||||||
with pytest.raises(serializers.ValidationError) 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 cannot be null.']
|
||||||
|
|
||||||
def test_allow_null(self):
|
def test_allow_null(self):
|
||||||
"""
|
"""
|
||||||
|
@ -66,7 +66,7 @@ class TestEmpty:
|
||||||
field = serializers.CharField()
|
field = serializers.CharField()
|
||||||
with pytest.raises(serializers.ValidationError) 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 cannot be blank.']
|
||||||
|
|
||||||
def test_allow_blank(self):
|
def test_allow_blank(self):
|
||||||
"""
|
"""
|
||||||
|
@ -290,6 +290,24 @@ class FieldValues:
|
||||||
for output_value, expected_output in get_items(self.outputs):
|
for output_value, expected_output in get_items(self.outputs):
|
||||||
assert self.field.to_representation(output_value) == expected_output
|
assert self.field.to_representation(output_value) == expected_output
|
||||||
|
|
||||||
|
@override_settings(LANGUAGE_CODE='es')
|
||||||
|
def test_invalid_inputs_translated(self):
|
||||||
|
"""
|
||||||
|
Ensure that invalid values raise the expected validation localized error.
|
||||||
|
"""
|
||||||
|
es_invalid_inputs = get_items(getattr(self, 'es_invalid_inputs', {}))
|
||||||
|
|
||||||
|
if not es_invalid_inputs:
|
||||||
|
return
|
||||||
|
|
||||||
|
field_kwargs = getattr(self, 'field_kwargs', {})
|
||||||
|
field = self.field.__class__(**field_kwargs)
|
||||||
|
|
||||||
|
for input_value, expected_failure in es_invalid_inputs:
|
||||||
|
with pytest.raises(serializers.ValidationError) as exc_info:
|
||||||
|
field.run_validation(input_value)
|
||||||
|
assert exc_info.value.detail == expected_failure
|
||||||
|
|
||||||
|
|
||||||
# Boolean types...
|
# Boolean types...
|
||||||
|
|
||||||
|
@ -309,7 +327,11 @@ class TestBooleanField(FieldValues):
|
||||||
}
|
}
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'foo': ['`foo` is not a valid boolean.'],
|
'foo': ['`foo` is not a valid boolean.'],
|
||||||
None: ['This field may not be null.']
|
None: ['This field cannot be null.']
|
||||||
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'foo': ['`foo` is not a valid boolean.'],
|
||||||
|
None: ['Este campo no puede ser nulo.']
|
||||||
}
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
'true': True,
|
'true': True,
|
||||||
|
@ -363,7 +385,10 @@ class TestCharField(FieldValues):
|
||||||
'abc': 'abc'
|
'abc': 'abc'
|
||||||
}
|
}
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'': ['This field may not be blank.']
|
'': ['This field cannot be blank.']
|
||||||
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'': [u'Este campo no puede estar vacío.']
|
||||||
}
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
1: '1',
|
1: '1',
|
||||||
|
@ -383,6 +408,9 @@ class TestEmailField(FieldValues):
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'examplecom': ['Enter a valid email address.']
|
'examplecom': ['Enter a valid email address.']
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'examplecom': [u'Introduzca una dirección de correo electrónico válida.']
|
||||||
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.EmailField()
|
field = serializers.EmailField()
|
||||||
|
|
||||||
|
@ -398,7 +426,8 @@ class TestRegexField(FieldValues):
|
||||||
'A9': ["This value does not match the required pattern."]
|
'A9': ["This value does not match the required pattern."]
|
||||||
}
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.RegexField(regex='[a-z][0-9]')
|
field_kwargs = {'regex': '[a-z][0-9]'}
|
||||||
|
field = serializers.RegexField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestSlugField(FieldValues):
|
class TestSlugField(FieldValues):
|
||||||
|
@ -411,6 +440,9 @@ class TestSlugField(FieldValues):
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'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."]
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'slug 99': [u"Introduzca un 'slug' válido, consistente en letras, números, guiones bajos o medios."]
|
||||||
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.SlugField()
|
field = serializers.SlugField()
|
||||||
|
|
||||||
|
@ -425,6 +457,9 @@ class TestURLField(FieldValues):
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'example.com': ['Enter a valid URL.']
|
'example.com': ['Enter a valid URL.']
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'example.com': [u'Introduzca una URL válida.']
|
||||||
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.URLField()
|
field = serializers.URLField()
|
||||||
|
|
||||||
|
@ -446,6 +481,9 @@ class TestIntegerField(FieldValues):
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'abc': ['A valid integer is required.']
|
'abc': ['A valid integer is required.']
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'abc': ['A valid integer is required.']
|
||||||
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
'1': 1,
|
'1': 1,
|
||||||
'0': 0,
|
'0': 0,
|
||||||
|
@ -480,18 +518,11 @@ class TestMinMaxIntegerField(FieldValues):
|
||||||
'4': [u'Asegúrese de que este valor es menor o igual a 3.'],
|
'4': [u'Asegúrese de que este valor es menor o igual a 3.'],
|
||||||
}
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.IntegerField(min_value=1, max_value=3)
|
field_kwargs = {
|
||||||
|
'min_value': 1,
|
||||||
@override_settings(LANGUAGE_CODE='es')
|
'max_value': 3,
|
||||||
def test_invalid_inputs_translated(self):
|
}
|
||||||
"""
|
field = serializers.IntegerField(**field_kwargs)
|
||||||
Ensure that invalid values raise the expected validation error.
|
|
||||||
"""
|
|
||||||
field = serializers.IntegerField(min_value=1, max_value=3)
|
|
||||||
for input_value, expected_failure in get_items(self.es_invalid_inputs):
|
|
||||||
with pytest.raises(serializers.ValidationError) as exc_info:
|
|
||||||
field.run_validation(input_value)
|
|
||||||
assert exc_info.value.detail == expected_failure
|
|
||||||
|
|
||||||
|
|
||||||
class TestFloatField(FieldValues):
|
class TestFloatField(FieldValues):
|
||||||
|
@ -509,6 +540,9 @@ class TestFloatField(FieldValues):
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'abc': ["A valid number is required."]
|
'abc': ["A valid number is required."]
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'abc': ['A valid number is required.']
|
||||||
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
'1': 1.0,
|
'1': 1.0,
|
||||||
'0': 0.0,
|
'0': 0.0,
|
||||||
|
@ -538,8 +572,15 @@ class TestMinMaxFloatField(FieldValues):
|
||||||
'0.0': ['Ensure this value is greater than or equal to 1.'],
|
'0.0': ['Ensure this value is greater than or equal to 1.'],
|
||||||
'3.1': ['Ensure this value is less than or equal to 3.'],
|
'3.1': ['Ensure this value is less than or equal to 3.'],
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
0.9: [u'Asegúrese de que este valor es mayor o igual a 1.'],
|
||||||
|
3.1: [u'Asegúrese de que este valor es menor o igual a 3.'],
|
||||||
|
'0.0': [u'Asegúrese de que este valor es mayor o igual a 1.'],
|
||||||
|
'3.1': [u'Asegúrese de que este valor es menor o igual a 3.'],
|
||||||
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.FloatField(min_value=1, max_value=3)
|
field_kwargs = {'min_value': 1, 'max_value': 3}
|
||||||
|
field = serializers.FloatField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestDecimalField(FieldValues):
|
class TestDecimalField(FieldValues):
|
||||||
|
@ -559,9 +600,17 @@ class TestDecimalField(FieldValues):
|
||||||
(Decimal('Nan'), ["A valid number is required."]),
|
(Decimal('Nan'), ["A valid number is required."]),
|
||||||
(Decimal('Inf'), ["A valid number is required."]),
|
(Decimal('Inf'), ["A valid number is required."]),
|
||||||
('12.345', ["Ensure that there are no more than 3 digits in total."]),
|
('12.345', ["Ensure that there are no more than 3 digits in total."]),
|
||||||
('0.01', ["Ensure that there are no more than 1 decimal places."]),
|
('0.01', ["Ensure that there are no more than 1 decimal place."]),
|
||||||
(123, ["Ensure that there are no more than 2 digits before the decimal point."])
|
(123, ["Ensure that there are no more than 2 digits before the decimal point."])
|
||||||
)
|
)
|
||||||
|
es_invalid_inputs = (
|
||||||
|
('abc', ["A valid number is required."]),
|
||||||
|
(Decimal('Nan'), ["A valid number is required."]),
|
||||||
|
(Decimal('Inf'), ["A valid number is required."]),
|
||||||
|
('12.345', [u'Asegúrese de que no hay más de 3 dígitos en total.']),
|
||||||
|
('0.01', [u'Asegúrese de que no haya más de 1 dígito decimal.']),
|
||||||
|
(123, [u'Asegúrese de que no haya más de 2 dígitos antes del punto decimal.'])
|
||||||
|
)
|
||||||
outputs = {
|
outputs = {
|
||||||
'1': '1.0',
|
'1': '1.0',
|
||||||
'0': '0.0',
|
'0': '0.0',
|
||||||
|
@ -574,7 +623,8 @@ class TestDecimalField(FieldValues):
|
||||||
Decimal('1.09'): '1.1',
|
Decimal('1.09'): '1.1',
|
||||||
Decimal('0.04'): '0.0'
|
Decimal('0.04'): '0.0'
|
||||||
}
|
}
|
||||||
field = serializers.DecimalField(max_digits=3, decimal_places=1)
|
field_kwargs = {'max_digits': 3, 'decimal_places': 1}
|
||||||
|
field = serializers.DecimalField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestMinMaxDecimalField(FieldValues):
|
class TestMinMaxDecimalField(FieldValues):
|
||||||
|
@ -589,11 +639,16 @@ class TestMinMaxDecimalField(FieldValues):
|
||||||
'9.9': ['Ensure this value is greater than or equal to 10.'],
|
'9.9': ['Ensure this value is greater than or equal to 10.'],
|
||||||
'20.1': ['Ensure this value is less than or equal to 20.'],
|
'20.1': ['Ensure this value is less than or equal to 20.'],
|
||||||
}
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'9.9': [u'Asegúrese de que este valor es mayor o igual a 10.'],
|
||||||
|
'20.1': [u'Asegúrese de que este valor es menor o igual a 20.'],
|
||||||
|
}
|
||||||
outputs = {}
|
outputs = {}
|
||||||
field = serializers.DecimalField(
|
field_kwargs = {
|
||||||
max_digits=3, decimal_places=1,
|
'max_digits': 3, 'decimal_places': 1,
|
||||||
min_value=10, max_value=20
|
'min_value': 10, 'max_value': 20
|
||||||
)
|
}
|
||||||
|
field = serializers.DecimalField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestNoStringCoercionDecimalField(FieldValues):
|
class TestNoStringCoercionDecimalField(FieldValues):
|
||||||
|
@ -610,10 +665,11 @@ 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 = serializers.DecimalField(
|
field_kwargs = {
|
||||||
max_digits=3, decimal_places=1,
|
'max_digits': 3, 'decimal_places': 1,
|
||||||
coerce_to_string=False
|
'coerce_to_string': False
|
||||||
)
|
}
|
||||||
|
field = serializers.DecimalField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
# Date & time serializers...
|
# Date & time serializers...
|
||||||
|
@ -648,7 +704,8 @@ 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 = serializers.DateField(input_formats=['%d %b %Y'])
|
field_kwargs = {'input_formats': ['%d %b %Y']}
|
||||||
|
field = serializers.DateField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestCustomOutputFormatDateField(FieldValues):
|
class TestCustomOutputFormatDateField(FieldValues):
|
||||||
|
@ -819,19 +876,23 @@ class TestChoiceField(FieldValues):
|
||||||
'good': 'good',
|
'good': 'good',
|
||||||
}
|
}
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'amazing': ['`amazing` is not a valid choice.']
|
'amazing': ["Value 'amazing' is not a valid choice."]
|
||||||
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'amazing': [u"Valor 'amazing' no es una opción válida."]
|
||||||
}
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
'good': 'good',
|
'good': 'good',
|
||||||
'': ''
|
'': ''
|
||||||
}
|
}
|
||||||
field = serializers.ChoiceField(
|
field_kwargs = {
|
||||||
choices=[
|
'choices': [
|
||||||
('poor', 'Poor quality'),
|
('poor', 'Poor quality'),
|
||||||
('medium', 'Medium quality'),
|
('medium', 'Medium quality'),
|
||||||
('good', 'Good quality'),
|
('good', 'Good quality'),
|
||||||
]
|
]
|
||||||
)
|
}
|
||||||
|
field = serializers.ChoiceField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestChoiceFieldWithType(FieldValues):
|
class TestChoiceFieldWithType(FieldValues):
|
||||||
|
@ -844,20 +905,25 @@ class TestChoiceFieldWithType(FieldValues):
|
||||||
3: 3,
|
3: 3,
|
||||||
}
|
}
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
5: ['`5` is not a valid choice.'],
|
5: ['Value 5 is not a valid choice.'],
|
||||||
'abc': ['`abc` is not a valid choice.']
|
'abc': ["Value 'abc' is not a valid choice."]
|
||||||
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
5: [u'Valor 5 no es una opción válida.'],
|
||||||
|
'abc': [u"Valor 'abc' no es una opción válida."]
|
||||||
}
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
'1': 1,
|
'1': 1,
|
||||||
1: 1
|
1: 1
|
||||||
}
|
}
|
||||||
field = serializers.ChoiceField(
|
field_kwargs = {
|
||||||
choices=[
|
'choices': [
|
||||||
(1, 'Poor quality'),
|
(1, 'Poor quality'),
|
||||||
(2, 'Medium quality'),
|
(2, 'Medium quality'),
|
||||||
(3, 'Good quality'),
|
(3, 'Good quality'),
|
||||||
]
|
]
|
||||||
)
|
}
|
||||||
|
field = serializers.ChoiceField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestChoiceFieldWithListChoices(FieldValues):
|
class TestChoiceFieldWithListChoices(FieldValues):
|
||||||
|
@ -871,12 +937,16 @@ class TestChoiceFieldWithListChoices(FieldValues):
|
||||||
'good': 'good',
|
'good': 'good',
|
||||||
}
|
}
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'awful': ['`awful` is not a valid choice.']
|
'awful': ["Value 'awful' is not a valid choice."]
|
||||||
|
}
|
||||||
|
es_invalid_inputs = {
|
||||||
|
'awful': [u"Valor 'awful' no es una opción válida."]
|
||||||
}
|
}
|
||||||
outputs = {
|
outputs = {
|
||||||
'good': 'good'
|
'good': 'good'
|
||||||
}
|
}
|
||||||
field = serializers.ChoiceField(choices=('poor', 'medium', 'good'))
|
field_kwargs = {'choices': ('poor', 'medium', 'good')}
|
||||||
|
field = serializers.ChoiceField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TestMultipleChoiceField(FieldValues):
|
class TestMultipleChoiceField(FieldValues):
|
||||||
|
@ -890,18 +960,19 @@ class TestMultipleChoiceField(FieldValues):
|
||||||
}
|
}
|
||||||
invalid_inputs = {
|
invalid_inputs = {
|
||||||
'abc': ['Expected a list of items but got type `str`.'],
|
'abc': ['Expected a list of items but got type `str`.'],
|
||||||
('aircon', 'incorrect'): ['`incorrect` is not a valid choice.']
|
('aircon', 'incorrect'): ["Value 'incorrect' is not a valid choice."]
|
||||||
}
|
}
|
||||||
outputs = [
|
outputs = [
|
||||||
(['aircon', 'manual'], set(['aircon', 'manual']))
|
(['aircon', 'manual'], set(['aircon', 'manual']))
|
||||||
]
|
]
|
||||||
field = serializers.MultipleChoiceField(
|
field_kwargs = {
|
||||||
choices=[
|
'choices': [
|
||||||
('aircon', 'AirCon'),
|
('aircon', 'AirCon'),
|
||||||
('manual', 'Manual drive'),
|
('manual', 'Manual drive'),
|
||||||
('diesel', 'Diesel'),
|
('diesel', 'Diesel'),
|
||||||
]
|
]
|
||||||
)
|
}
|
||||||
|
field = serializers.MultipleChoiceField(**field_kwargs)
|
||||||
|
|
||||||
|
|
||||||
# File serializers...
|
# File serializers...
|
||||||
|
|
|
@ -302,7 +302,7 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
|
serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEqual(serializer.errors, {'target': ['This field may not be null.']})
|
self.assertEqual(serializer.errors, {'target': ['This field cannot be null.']})
|
||||||
|
|
||||||
|
|
||||||
class HyperlinkedNullableForeignKeyTests(TestCase):
|
class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
|
|
|
@ -282,7 +282,7 @@ class PKForeignKeyTests(TestCase):
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data)
|
serializer = ForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEqual(serializer.errors, {'target': ['This field may not be null.']})
|
self.assertEqual(serializer.errors, {'target': ['This field cannot be null.']})
|
||||||
|
|
||||||
def test_foreign_key_with_empty(self):
|
def test_foreign_key_with_empty(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -160,7 +160,7 @@ class SlugForeignKeyTests(TestCase):
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data)
|
serializer = ForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEqual(serializer.errors, {'target': ['This field may not be null.']})
|
self.assertEqual(serializer.errors, {'target': ['This field cannot be null.']})
|
||||||
|
|
||||||
|
|
||||||
class SlugNullableForeignKeyTests(TestCase):
|
class SlugNullableForeignKeyTests(TestCase):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user