aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorIan Strachan2012-10-22 22:24:26 +0100
committerIan Strachan2012-10-22 22:24:26 +0100
commitc7a0d52fd7e22fbc4a01ff900bd3b2c1215e984d (patch)
tree164bc17f49ff80155edf846e94855369b8228878 /rest_framework
parentaba0172f5c988af145113678fe3d4f411111d4ff (diff)
downloaddjango-rest-framework-c7a0d52fd7e22fbc4a01ff900bd3b2c1215e984d.tar.bz2
#314 Fix for manytomany field being required in the payload even though the field is specified as readonly in the serializer
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/fields.py3
-rw-r--r--rest_framework/tests/models.py5
-rw-r--r--rest_framework/tests/serializer.py54
3 files changed, 62 insertions, 0 deletions
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index f610d6aa..6ed37823 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -256,6 +256,9 @@ class ManyRelatedMixin(object):
return [self.to_native(item) for item in value.all()]
def field_from_native(self, data, field_name, into):
+ if self.readonly:
+ return
+
try:
# Form data
value = data.getlist(self.source or field_name)
diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py
index 8e721737..97cd0849 100644
--- a/rest_framework/tests/models.py
+++ b/rest_framework/tests/models.py
@@ -62,7 +62,12 @@ class CallableDefaultValueModel(RESTFrameworkModel):
class ManyToManyModel(RESTFrameworkModel):
rel = models.ManyToManyField(Anchor)
+
+class ReadOnlyManyToManyModel(RESTFrameworkModel):
+ text = models.CharField(max_length=100, default='anchor')
+ rel = models.ManyToManyField(Anchor)
+
# Models to test generic relations
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 2dfc04e1..c614b66a 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -246,6 +246,60 @@ class ManyToManyTests(TestCase):
self.assertEquals(len(ManyToManyModel.objects.all()), 2)
self.assertEquals(instance.pk, 2)
self.assertEquals(list(instance.rel.all()), [])
+
+class ReadOnlyManyToManyTests(TestCase):
+ def setUp(self):
+ class ReadOnlyManyToManySerializer(serializers.ModelSerializer):
+ rel = serializers.ManyRelatedField(readonly=True)
+ class Meta:
+ model = ReadOnlyManyToManyModel
+
+ self.serializer_class = ReadOnlyManyToManySerializer
+
+ # An anchor instance to use for the relationship
+ self.anchor = Anchor()
+ self.anchor.save()
+
+ # A model instance with a many to many relationship to the anchor
+ self.instance = ReadOnlyManyToManyModel()
+ self.instance.save()
+ self.instance.rel.add(self.anchor)
+
+ # A serialized representation of the model instance
+ self.data = {'rel': [self.anchor.id], 'id': 1, 'text': 'anchor'}
+
+
+ def test_update(self):
+ """
+ Attempt to update an instance of a model with a ManyToMany
+ relationship. Not updated due to readonly=True
+ """
+ new_anchor = Anchor()
+ new_anchor.save()
+ data = {'rel': [self.anchor.id, new_anchor.id]}
+ serializer = self.serializer_class(data, instance=self.instance)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ReadOnlyManyToManyModel.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ # rel is still as original (1 entry)
+ self.assertEquals(list(instance.rel.all()), [self.anchor])
+
+ def test_update_without_relationship(self):
+ """
+ Attempt to update an instance of a model where many to ManyToMany
+ relationship is not supplied. Not updated due to readonly=True
+ """
+ new_anchor = Anchor()
+ new_anchor.save()
+ data = {}
+ serializer = self.serializer_class(data, instance=self.instance)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ReadOnlyManyToManyModel.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ # rel is still as original (1 entry)
+ self.assertEquals(list(instance.rel.all()), [self.anchor])
class DefaultValueTests(TestCase):