-
-
+
+
--
cgit v1.2.3
From a3a06d11cc39da55d34f99e272bf092a2dcd4c5c Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Mon, 28 Jan 2013 12:56:42 +0000
Subject: Ensure model field validation is performed for ModelSerializers with
a custom restore_object method. Fixes #623.
---
rest_framework/serializers.py | 30 ++++++++++++++++++++++++------
rest_framework/tests/serializer.py | 27 +++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 6 deletions(-)
(limited to 'rest_framework')
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 6ecc7b45..0fed2c29 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -513,6 +513,22 @@ class ModelSerializer(Serializer):
exclusions.remove(field_name)
return exclusions
+ def full_clean(self, instance):
+ """
+ Perform Django's full_clean, and populate the `errors` dictionary
+ if any validation errors occur.
+
+ Note that we don't perform this inside the `.restore_object()` method,
+ so that subclasses can override `.restore_object()`, and still get
+ the full_clean validation checking.
+ """
+ try:
+ instance.full_clean(exclude=self.get_validation_exclusions())
+ except ValidationError, err:
+ self._errors = err.message_dict
+ return None
+ return instance
+
def restore_object(self, attrs, instance=None):
"""
Restore the model instance.
@@ -544,14 +560,16 @@ class ModelSerializer(Serializer):
else:
instance = self.opts.model(**attrs)
- try:
- instance.full_clean(exclude=self.get_validation_exclusions())
- except ValidationError, err:
- self._errors = err.message_dict
- return None
-
return instance
+ def from_native(self, data, files):
+ """
+ Override the default method to also include model field validation.
+ """
+ instance = super(ModelSerializer, self).from_native(data, files)
+ if instance:
+ return self.full_clean(instance)
+
def save(self):
"""
Save the deserialized object and return it.
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index b4428ca3..48b4f1ab 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -54,6 +54,19 @@ class ActionItemSerializer(serializers.ModelSerializer):
model = ActionItem
+class ActionItemSerializerCustomRestore(serializers.ModelSerializer):
+
+ class Meta:
+ model = ActionItem
+
+ def restore_object(self, data, instance=None):
+ if instance is None:
+ return ActionItem(**data)
+ for key, val in data.items():
+ setattr(instance, key, val)
+ return instance
+
+
class PersonSerializer(serializers.ModelSerializer):
info = serializers.Field(source='info')
@@ -273,6 +286,20 @@ class ValidationTests(TestCase):
self.assertEquals(serializer.is_valid(), False)
self.assertEquals(serializer.errors, {'title': [u'Ensure this value has at most 200 characters (it has 201).']})
+ def test_modelserializer_max_length_exceeded_with_custom_restore(self):
+ """
+ When overriding ModelSerializer.restore_object, validation tests should still apply.
+ Regression test for #623.
+
+ https://github.com/tomchristie/django-rest-framework/pull/623
+ """
+ data = {
+ 'title': 'x' * 201,
+ }
+ serializer = ActionItemSerializerCustomRestore(data=data)
+ self.assertEquals(serializer.is_valid(), False)
+ self.assertEquals(serializer.errors, {'title': [u'Ensure this value has at most 200 characters (it has 201).']})
+
def test_default_modelfield_max_length_exceeded(self):
data = {
'title': 'Testing "info" field...',
--
cgit v1.2.3
From 85e6360792e1adbee1d457e25dc2d357c6d55adc Mon Sep 17 00:00:00 2001
From: Andrea de Marco
Date: Mon, 28 Jan 2013 22:08:40 +0100
Subject: Update rest_framework/serializers.py
---
rest_framework/serializers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'rest_framework')
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 0fed2c29..4fb802a7 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -469,7 +469,7 @@ class ModelSerializer(Serializer):
kwargs['required'] = False
kwargs['default'] = model_field.get_default()
- if model_field.__class__ == models.TextField:
+ if issubclass(model_field.__class__, models.TextField):
kwargs['widget'] = widgets.Textarea
# TODO: TypedChoiceField?
--
cgit v1.2.3
From fceacd830fcd3b67425dafd5b0e6dcc5b285b6ca Mon Sep 17 00:00:00 2001
From: Fernando Rocha
Date: Tue, 29 Jan 2013 18:46:05 -0300
Subject: Fix processing of ManyToManyField when it is empty
Signed-off-by: Fernando Rocha
---
rest_framework/relations.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'rest_framework')
diff --git a/rest_framework/relations.py b/rest_framework/relations.py
index af63ceaa..dc0a73e6 100644
--- a/rest_framework/relations.py
+++ b/rest_framework/relations.py
@@ -148,7 +148,7 @@ class ManyRelatedMixin(object):
value = data.getlist(self.source or field_name)
except:
# Non-form data
- value = data.get(self.source or field_name)
+ value = data.get(self.source or field_name, [])
else:
if value == ['']:
value = []
--
cgit v1.2.3
From 41364b3be0536a606d9b41d3792c2e562b860360 Mon Sep 17 00:00:00 2001
From: Fernando Rocha
Date: Wed, 30 Jan 2013 09:09:17 -0300
Subject: Added regretion test for issue #632
Signed-off-by: Fernando Rocha
---
rest_framework/tests/relations.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
(limited to 'rest_framework')
diff --git a/rest_framework/tests/relations.py b/rest_framework/tests/relations.py
index 91daea8a..edc85f9e 100644
--- a/rest_framework/tests/relations.py
+++ b/rest_framework/tests/relations.py
@@ -31,3 +31,17 @@ class FieldTests(TestCase):
field = serializers.SlugRelatedField(queryset=NullModel.objects.all(), slug_field='pk')
self.assertRaises(serializers.ValidationError, field.from_native, '')
self.assertRaises(serializers.ValidationError, field.from_native, [])
+
+
+class TestManyRelateMixin(TestCase):
+ def test_missing_many_to_many_related_field(self):
+ '''
+ Regression test for #632
+
+ https://github.com/tomchristie/django-rest-framework/pull/632
+ '''
+ field = serializers.ManyRelatedField(read_only=False)
+
+ into = {}
+ field.field_from_native({}, None, 'field_name', into)
+ self.assertEqual(into['field_name'], [])
--
cgit v1.2.3