This commit is contained in:
Yuri Prezument 2014-01-07 19:10:08 -08:00
commit f314d8d966
4 changed files with 37 additions and 6 deletions

View File

@ -157,23 +157,24 @@ Corresponds to `django.db.models.fields.BooleanField`.
## CharField
A text representation, optionally validates the text to be shorter than `max_length` and longer than `min_length`.
If `allow_none` is `False` (default), `None` values will be converted to an empty string.
Corresponds to `django.db.models.fields.CharField`
or `django.db.models.fields.TextField`.
**Signature:** `CharField(max_length=None, min_length=None)`
**Signature:** `CharField(max_length=None, min_length=None, allow_none=False)`
## URLField
Corresponds to `django.db.models.fields.URLField`. Uses Django's `django.core.validators.URLValidator` for validation.
**Signature:** `CharField(max_length=200, min_length=None)`
**Signature:** `CharField(max_length=200, min_length=None, allow_none=False)`
## SlugField
Corresponds to `django.db.models.fields.SlugField`.
**Signature:** `CharField(max_length=50, min_length=None)`
**Signature:** `CharField(max_length=50, min_length=None, allow_none=False)`
## ChoiceField

View File

@ -448,8 +448,9 @@ class CharField(WritableField):
type_label = 'string'
form_field_class = forms.CharField
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
def __init__(self, max_length=None, min_length=None, allow_none=False, *args, **kwargs):
self.max_length, self.min_length = max_length, min_length
self.allow_none = allow_none
super(CharField, self).__init__(*args, **kwargs)
if min_length is not None:
self.validators.append(validators.MinLengthValidator(min_length))
@ -457,7 +458,9 @@ class CharField(WritableField):
self.validators.append(validators.MaxLengthValidator(max_length))
def from_native(self, value):
if isinstance(value, six.string_types) or value is None:
if value is None and not self.allow_none:
return ''
if isinstance(value, six.string_types):
return value
return smart_text(value)

View File

@ -836,10 +836,15 @@ class ModelSerializer(Serializer):
kwargs.update({attribute: getattr(model_field, attribute)})
try:
return self.field_mapping[model_field.__class__](**kwargs)
field_class = self.field_mapping[model_field.__class__]
except KeyError:
return ModelField(model_field=model_field, **kwargs)
if issubclass(field_class, CharField) and model_field.null:
kwargs['allow_none'] = True
return field_class(**kwargs)
def get_validation_exclusions(self):
"""
Return a list of field names to exclude from model validation.

View File

@ -1124,6 +1124,20 @@ class BlankFieldTests(TestCase):
serializer = self.model_serializer_class(data={})
self.assertEqual(serializer.is_valid(), True)
def test_create_model_null_field_save(self):
"""
Regression test for #1330.
https://github.com/tomchristie/django-rest-framework/pull/1330
"""
serializer = self.model_serializer_class(data={'title': None})
self.assertEqual(serializer.is_valid(), True)
try:
serializer.save()
except Exception:
self.fail('Exception raised on save() after validation passes')
#test for issue #460
class SerializerPickleTests(TestCase):
@ -1490,6 +1504,7 @@ class AttributeMappingOnAutogeneratedFieldsTests(TestCase):
image_field = models.ImageField(max_length=1024, blank=True)
slug_field = models.SlugField(max_length=1024, blank=True)
url_field = models.URLField(max_length=1024, blank=True)
nullable_char_field = models.CharField(max_length=1024, blank=True, null=True)
class AMOAFSerializer(serializers.ModelSerializer):
class Meta:
@ -1522,6 +1537,10 @@ class AttributeMappingOnAutogeneratedFieldsTests(TestCase):
'url_field': [
('max_length', 1024),
],
'nullable_char_field': [
('max_length', 1024),
('allow_none', True),
],
}
def field_test(self, field):
@ -1558,6 +1577,9 @@ class AttributeMappingOnAutogeneratedFieldsTests(TestCase):
def test_url_field(self):
self.field_test('url_field')
def test_nullable_char_field(self):
self.field_test('nullable_char_field')
class DefaultValuesOnAutogeneratedFieldsTests(TestCase):