mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-03 20:10:10 +03:00
Merge branch 'master' of https://github.com/un33k/django-rest-framework
This commit is contained in:
commit
1f9a000b0f
|
@ -346,7 +346,13 @@ class BaseSerializer(WritableField):
|
|||
continue
|
||||
field.initialize(parent=self, field_name=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)
|
||||
if callable(method):
|
||||
value = method(obj, value)
|
||||
|
@ -386,6 +392,9 @@ class BaseSerializer(WritableField):
|
|||
Override default so that the serializer can be used as a nested field
|
||||
across relationships.
|
||||
"""
|
||||
if field_name in self.opts.non_native_fields:
|
||||
return None
|
||||
|
||||
if self.write_only:
|
||||
return None
|
||||
|
||||
|
@ -622,6 +631,7 @@ class ModelSerializerOptions(SerializerOptions):
|
|||
self.model = getattr(meta, 'model', None)
|
||||
self.read_only_fields = getattr(meta, 'read_only_fields', ())
|
||||
self.write_only_fields = getattr(meta, 'write_only_fields', ())
|
||||
self.non_native_fields = getattr(meta, 'non_native_fields', ())
|
||||
|
||||
|
||||
class ModelSerializer(Serializer):
|
||||
|
@ -782,7 +792,7 @@ class ModelSerializer(Serializer):
|
|||
"Non-existant field '%s' specified in `write_only_fields` "
|
||||
"on serializer '%s'." %
|
||||
(field_name, self.__class__.__name__))
|
||||
ret[field_name].write_only = True
|
||||
ret[field_name].write_only = True
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -923,6 +933,10 @@ class ModelSerializer(Serializer):
|
|||
nested_forward_relations = {}
|
||||
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
|
||||
for (obj, model) in meta.get_all_related_objects_with_model():
|
||||
field_name = obj.get_accessor_name()
|
||||
|
|
51
rest_framework/tests/test_non_native_fields.py
Normal file
51
rest_framework/tests/test_non_native_fields.py
Normal 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'])
|
Loading…
Reference in New Issue
Block a user