mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-04 12:30:11 +03:00
Merge de8742116a
into d34dfc3fac
This commit is contained in:
commit
c8ac7f6092
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user