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
|
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)
|
||||||
|
try:
|
||||||
value = field.field_to_native(obj, field_name)
|
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):
|
||||||
|
@ -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()
|
||||||
|
|
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