This commit is contained in:
Federico Capoano 2014-03-20 10:42:39 +01:00
commit 1f9a000b0f
2 changed files with 67 additions and 2 deletions

View File

@ -346,7 +346,13 @@ class BaseSerializer(WritableField):
continue continue
field.initialize(parent=self, field_name=field_name) field.initialize(parent=self, field_name=field_name)
key = self.get_field_key(field_name) key = self.get_field_key(field_name)
value = field.field_to_native(obj, field_name) try:
value = field.field_to_native(obj, field_name)
except AttributeError:
if field_name in self.opts.non_native_fields:
continue
else:
raise
method = getattr(self, 'transform_%s' % field_name, None) method = getattr(self, 'transform_%s' % field_name, None)
if callable(method): if callable(method):
value = method(obj, value) value = method(obj, value)
@ -386,6 +392,9 @@ class BaseSerializer(WritableField):
Override default so that the serializer can be used as a nested field Override default so that the serializer can be used as a nested field
across relationships. across relationships.
""" """
if field_name in self.opts.non_native_fields:
return None
if self.write_only: if self.write_only:
return None return None
@ -622,6 +631,7 @@ class ModelSerializerOptions(SerializerOptions):
self.model = getattr(meta, 'model', None) self.model = getattr(meta, 'model', None)
self.read_only_fields = getattr(meta, 'read_only_fields', ()) self.read_only_fields = getattr(meta, 'read_only_fields', ())
self.write_only_fields = getattr(meta, 'write_only_fields', ()) self.write_only_fields = getattr(meta, 'write_only_fields', ())
self.non_native_fields = getattr(meta, 'non_native_fields', ())
class ModelSerializer(Serializer): class ModelSerializer(Serializer):
@ -782,7 +792,7 @@ class ModelSerializer(Serializer):
"Non-existant field '%s' specified in `write_only_fields` " "Non-existant field '%s' specified in `write_only_fields` "
"on serializer '%s'." % "on serializer '%s'." %
(field_name, self.__class__.__name__)) (field_name, self.__class__.__name__))
ret[field_name].write_only = True ret[field_name].write_only = True
return ret return ret
@ -923,6 +933,10 @@ class ModelSerializer(Serializer):
nested_forward_relations = {} nested_forward_relations = {}
meta = self.opts.model._meta meta = self.opts.model._meta
for field_name in self.opts.non_native_fields:
if field_name in attrs:
attrs.pop(field_name)
# Reverse fk or one-to-one relations # Reverse fk or one-to-one relations
for (obj, model) in meta.get_all_related_objects_with_model(): for (obj, model) in meta.get_all_related_objects_with_model():
field_name = obj.get_accessor_name() field_name = obj.get_accessor_name()

View File

@ -0,0 +1,51 @@
from django.db import models
from django.test import TestCase
from rest_framework import serializers
class ExampleModel(models.Model):
email = models.EmailField(max_length=100)
password = models.CharField(max_length=100)
class ExampleSerializer(serializers.ModelSerializer):
password_confirmation = serializers.CharField()
def validate_password_confirmation(self, attrs, source):
password_confirmation = attrs[source]
password = attrs['password']
if password_confirmation != password:
raise serializers.ValidationError('Password confirmation mismatch')
attrs.pop(source)
return attrs
class Meta:
model = ExampleModel
fields = ('email', 'password', 'password_confirmation',)
write_only_fields = ('password',)
non_native_fields = ('password_confirmation',)
class NonNativeFieldTests(TestCase):
def test_non_native_fields(self):
data = {
'email': 'foo@example.com',
'password': '123',
'password_confirmation': '123',
}
serializer = ExampleSerializer(data=data)
self.assertTrue(serializer.is_valid())
self.assertTrue(isinstance(serializer.object, ExampleModel))
self.assertEquals(serializer.object.email, data['email'])
self.assertEquals(serializer.object.password, data['password'])
self.assertEquals(serializer.data, {'email': 'foo@example.com'})
def test_non_native_fields_validation_error(self):
data = {
'email': 'foo@example.com',
'password': '123',
'password_confirmation': 'abc',
}
serializer = ExampleSerializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertEquals(len(serializer.errors), 1)
self.assertEquals(serializer.errors['password_confirmation'],
['Password confirmation mismatch'])