Make modelserializer support writable properties on models it instantiates.

This commit is contained in:
Craig de Stigter 2013-09-06 16:18:01 +12:00
parent b47f1b0257
commit e32e464d45
3 changed files with 55 additions and 12 deletions

View File

@ -858,14 +858,18 @@ class ModelSerializer(Serializer):
if isinstance(self.fields.get(field_name, None), Serializer): if isinstance(self.fields.get(field_name, None), Serializer):
nested_forward_relations[field_name] = attrs[field_name] nested_forward_relations[field_name] = attrs[field_name]
# Update an existing instance... if instance is None:
if instance is not None: # Create a new instance, if we need to
for key, val in attrs.items(): field_attrs = {}
setattr(instance, key, val) for field_name in meta.get_all_field_names():
if field_name in attrs:
field_attrs[field_name] = attrs.pop(field_name)
# ...or create a new instance instance = self.opts.model(**field_attrs)
else:
instance = self.opts.model(**attrs) # Update an existing instance...
for key, val in attrs.items():
setattr(instance, key, val)
# Any relations that cannot be set until we've # Any relations that cannot be set until we've
# saved the model get hidden away on these # saved the model get hidden away on these

View File

@ -81,10 +81,16 @@ class Person(RESTFrameworkModel):
@property @property
def info(self): def info(self):
return { if not hasattr(self, '_info'):
'name': self.name, self._info = {
'age': self.age, 'name': self.name,
} 'age': self.age,
}
return self._info
@info.setter
def info(self, value):
self._info = value
class BlogPost(RESTFrameworkModel): class BlogPost(RESTFrameworkModel):
@ -163,6 +169,18 @@ class NullableOneToOneSource(RESTFrameworkModel):
related_name='nullable_source') related_name='nullable_source')
class ModelWithWritableProperty(RESTFrameworkModel):
name = models.CharField(max_length=100)
@property
def prop(self):
return getattr(self, '_value', 'hi!')
@prop.setter
def prop(self, value):
self._value = value
# Serializer used to test BasicModel # Serializer used to test BasicModel
class BasicModelSerializer(serializers.ModelSerializer): class BasicModelSerializer(serializers.ModelSerializer):
class Meta: class Meta:

View File

@ -7,7 +7,7 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, fields, relations from rest_framework import serializers, fields, relations
from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel, BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,
ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, RESTFrameworkModel) ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, RESTFrameworkModel, ModelWithWritableProperty)
from rest_framework.tests.models import BasicModelSerializer from rest_framework.tests.models import BasicModelSerializer
import datetime import datetime
import pickle import pickle
@ -1643,3 +1643,24 @@ class SerializerSupportsManyRelationships(TestCase):
serializer = SimpleSlugSourceModelSerializer(data={'text': 'foo', 'targets': [1, 2]}) serializer = SimpleSlugSourceModelSerializer(data={'text': 'foo', 'targets': [1, 2]})
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, {'text': 'foo', 'targets': [1, 2]}) self.assertEqual(serializer.data, {'text': 'foo', 'targets': [1, 2]})
class WritablePropertyModelSerializer(serializers.ModelSerializer):
prop = serializers.CharField(source='prop')
class Meta:
model = ModelWithWritableProperty
fields = ('name', 'prop',)
class ModelSerializerSupportsWritableProperty(TestCase):
def setUp(self):
ModelWithWritableProperty.objects.create(name='hey! ')
def test_modelserializer_create_with_property(self):
s = WritablePropertyModelSerializer(data={
'name': 'the name',
'prop': 'new value',
})
self.assertTrue(s.is_valid())
obj = s.save()
self.assertEqual(obj.prop, 'new value')