This commit is contained in:
pySilver 2014-08-18 14:55:44 +00:00
commit c8ac7f6092
5 changed files with 38 additions and 9 deletions

View File

@ -429,6 +429,11 @@ class ModelField(WritableField):
"type": self.model_field.get_internal_type()
}
def validate(self, value):
super(ModelField, self).validate(value)
if value is None and not self.model_field.null:
raise ValidationError(self.error_messages['invalid'])
##### Typed Fields #####
@ -474,10 +479,7 @@ class CharField(WritableField):
self.validators.append(validators.MaxLengthValidator(max_length))
def from_native(self, value):
if isinstance(value, six.string_types):
return value
if value is None:
if value in validators.EMPTY_VALUES:
return ''
return smart_text(value)

View File

@ -33,7 +33,7 @@ class RelatedField(WritableField):
many_widget = widgets.SelectMultiple
form_field_class = forms.ChoiceField
many_form_field_class = forms.MultipleChoiceField
null_values = (None, '', 'None')
null_values = (None, '', 'None', [], (), {})
cache_choices = False
empty_label = None
@ -182,7 +182,7 @@ class RelatedField(WritableField):
if value in self.null_values:
if self.required:
raise ValidationError(self.error_messages['required'])
into[(self.source or field_name)] = None
into[(self.source or field_name)] = [] if self.many else None
elif self.many:
into[(self.source or field_name)] = [self.from_native(item) for item in value]
else:

View File

@ -18,6 +18,7 @@ import types
from decimal import Decimal
from django.contrib.contenttypes.generic import GenericForeignKey
from django.core.paginator import Page
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.forms import widgets
from django.utils.datastructures import SortedDict
@ -912,9 +913,19 @@ class ModelSerializer(Serializer):
for field_name, field in self.fields.items():
field_name = field.source or field_name
# PY3 compat problem with ManyToManyField & OneToOneField
# hasattr in PY2 catches all exceptions, but in PY3 it only looks
# for AttributeError
# @see: https://code.djangoproject.com/ticket/22839
try:
field_exists = hasattr(instance, field_name)
except (AttributeError, ValueError, ObjectDoesNotExist):
field_exists = False
if field_name in exclusions \
and not field.read_only \
and (field.required or hasattr(instance, field_name)) \
and (field.required or field_exists) \
and not isinstance(field, Serializer):
exclusions.remove(field_name)
return exclusions

View File

@ -52,7 +52,7 @@ class CallableDefaultValueModel(RESTFrameworkModel):
class ManyToManyModel(RESTFrameworkModel):
rel = models.ManyToManyField(Anchor, help_text='Some help text.')
rel = models.ManyToManyField(Anchor, help_text='Some help text.', blank=True)
class ReadOnlyManyToManyModel(RESTFrameworkModel):

View File

@ -3,6 +3,7 @@ General tests for relational fields.
"""
from __future__ import unicode_literals
from django import get_version
from django.core.exceptions import ValidationError
from django.db import models
from django.test import TestCase
from django.utils import unittest
@ -43,12 +44,27 @@ class TestManyRelatedMixin(TestCase):
https://github.com/tomchristie/django-rest-framework/pull/632
'''
field = serializers.RelatedField(many=True, read_only=False)
field = serializers.RelatedField(many=True, read_only=False, required=False)
into = {}
field.field_from_native({}, None, 'field_name', into)
self.assertEqual(into['field_name'], [])
def test_missing_required_many_to_many_related_field(self):
'''
Missing but required many-to-many relationship should cause
ValidationError
'''
field = serializers.RelatedField(many=True, read_only=False)
into = {}
self.assertRaises(
ValidationError,
field.field_from_native,
{}, None, 'field_name', into
)
self.assertDictEqual(into, {})
# Regression tests for #694 (`source` attribute on related fields)