mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-23 15:54:16 +03:00
Partial support
This commit is contained in:
parent
3a5335f09f
commit
417fe1b675
|
@ -109,8 +109,7 @@ class Field(object):
|
||||||
def __init__(self, read_only=False, write_only=False,
|
def __init__(self, read_only=False, write_only=False,
|
||||||
required=None, default=empty, initial=None, source=None,
|
required=None, default=empty, initial=None, source=None,
|
||||||
label=None, help_text=None, style=None,
|
label=None, help_text=None, style=None,
|
||||||
error_messages=None, validators=[], allow_null=False,
|
error_messages=None, validators=[], allow_null=False):
|
||||||
context=None):
|
|
||||||
self._creation_counter = Field._creation_counter
|
self._creation_counter = Field._creation_counter
|
||||||
Field._creation_counter += 1
|
Field._creation_counter += 1
|
||||||
|
|
||||||
|
@ -139,7 +138,6 @@ class Field(object):
|
||||||
# These are set up by `.bind()` when the field is added to a serializer.
|
# These are set up by `.bind()` when the field is added to a serializer.
|
||||||
self.field_name = None
|
self.field_name = None
|
||||||
self.parent = None
|
self.parent = None
|
||||||
self._context = {} if (context is None) else context
|
|
||||||
|
|
||||||
# Collect default error message from self and parent classes
|
# Collect default error message from self and parent classes
|
||||||
messages = {}
|
messages = {}
|
||||||
|
@ -163,13 +161,6 @@ class Field(object):
|
||||||
kwargs = copy.deepcopy(self._kwargs)
|
kwargs = copy.deepcopy(self._kwargs)
|
||||||
return self.__class__(*args, **kwargs)
|
return self.__class__(*args, **kwargs)
|
||||||
|
|
||||||
@property
|
|
||||||
def context(self):
|
|
||||||
root = self
|
|
||||||
while root.parent is not None:
|
|
||||||
root = root.parent
|
|
||||||
return root._context
|
|
||||||
|
|
||||||
def bind(self, field_name, parent):
|
def bind(self, field_name, parent):
|
||||||
"""
|
"""
|
||||||
Setup the context for the field instance.
|
Setup the context for the field instance.
|
||||||
|
@ -254,6 +245,8 @@ class Field(object):
|
||||||
"""
|
"""
|
||||||
if data is empty:
|
if data is empty:
|
||||||
if self.required:
|
if self.required:
|
||||||
|
if getattr(self.root, 'partial', False):
|
||||||
|
raise SkipField()
|
||||||
self.fail('required')
|
self.fail('required')
|
||||||
return self.get_default()
|
return self.get_default()
|
||||||
|
|
||||||
|
@ -304,7 +297,29 @@ class Field(object):
|
||||||
raise AssertionError(msg)
|
raise AssertionError(msg)
|
||||||
raise ValidationError(msg.format(**kwargs))
|
raise ValidationError(msg.format(**kwargs))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def root(self):
|
||||||
|
"""
|
||||||
|
Returns the top-level serializer for this field.
|
||||||
|
"""
|
||||||
|
root = self
|
||||||
|
while root.parent is not None:
|
||||||
|
root = root.parent
|
||||||
|
return root
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self):
|
||||||
|
"""
|
||||||
|
Returns the context as passed to the root serializer on initialization.
|
||||||
|
"""
|
||||||
|
return getattr(self.root, '_context', {})
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
"""
|
||||||
|
Fields are represented using their initial calling arguments.
|
||||||
|
This allows us to create descriptive representations for serializer
|
||||||
|
instances that show all the declared fields on the serializer.
|
||||||
|
"""
|
||||||
return representation.field_repr(self)
|
return representation.field_repr(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -181,8 +181,9 @@ class BindingDict(object):
|
||||||
@six.add_metaclass(SerializerMetaclass)
|
@six.add_metaclass(SerializerMetaclass)
|
||||||
class Serializer(BaseSerializer):
|
class Serializer(BaseSerializer):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs.pop('partial', None)
|
|
||||||
kwargs.pop('many', None)
|
kwargs.pop('many', None)
|
||||||
|
self.partial = kwargs.pop('partial', False)
|
||||||
|
self._context = kwargs.pop('context', {})
|
||||||
|
|
||||||
super(Serializer, self).__init__(*args, **kwargs)
|
super(Serializer, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -289,7 +290,8 @@ class ListSerializer(BaseSerializer):
|
||||||
self.child = kwargs.pop('child', copy.deepcopy(self.child))
|
self.child = kwargs.pop('child', copy.deepcopy(self.child))
|
||||||
assert self.child is not None, '`child` is a required argument.'
|
assert self.child is not None, '`child` is a required argument.'
|
||||||
assert not inspect.isclass(self.child), '`child` has not been instantiated.'
|
assert not inspect.isclass(self.child), '`child` has not been instantiated.'
|
||||||
kwargs.pop('partial', None)
|
self.partial = kwargs.pop('partial', False)
|
||||||
|
self._context = kwargs.pop('context', {})
|
||||||
|
|
||||||
super(ListSerializer, self).__init__(*args, **kwargs)
|
super(ListSerializer, self).__init__(*args, **kwargs)
|
||||||
self.child.bind(field_name='', parent=self)
|
self.child.bind(field_name='', parent=self)
|
||||||
|
|
|
@ -1,3 +1,35 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
# Tests for core functionality.
|
||||||
|
# -----------------------------
|
||||||
|
|
||||||
|
class TestSerializer:
|
||||||
|
def setup(self):
|
||||||
|
class ExampleSerializer(serializers.Serializer):
|
||||||
|
char = serializers.CharField()
|
||||||
|
integer = serializers.IntegerField()
|
||||||
|
self.Serializer = ExampleSerializer
|
||||||
|
|
||||||
|
def test_valid_serializer(self):
|
||||||
|
serializer = self.Serializer(data={'char': 'abc', 'integer': 123})
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {'char': 'abc', 'integer': 123}
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
def test_invalid_serializer(self):
|
||||||
|
serializer = self.Serializer(data={'char': 'abc'})
|
||||||
|
assert not serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {}
|
||||||
|
assert serializer.errors == {'integer': ['This field is required.']}
|
||||||
|
|
||||||
|
def test_partial_validation(self):
|
||||||
|
serializer = self.Serializer(data={'char': 'abc'}, partial=True)
|
||||||
|
assert serializer.is_valid()
|
||||||
|
assert serializer.validated_data == {'char': 'abc'}
|
||||||
|
assert serializer.errors == {}
|
||||||
|
|
||||||
|
|
||||||
# # -*- coding: utf-8 -*-
|
# # -*- coding: utf-8 -*-
|
||||||
# from __future__ import unicode_literals
|
# from __future__ import unicode_literals
|
||||||
# from django.db import models
|
# from django.db import models
|
||||||
|
@ -334,7 +366,6 @@
|
||||||
# Check _data attribute is cleared on `save()`
|
# Check _data attribute is cleared on `save()`
|
||||||
|
|
||||||
# Regression test for #1116
|
# Regression test for #1116
|
||||||
# — id field is not populated if `data` is accessed prior to `save()`
|
|
||||||
# """
|
# """
|
||||||
# serializer = ActionItemSerializer(self.actionitem)
|
# serializer = ActionItemSerializer(self.actionitem)
|
||||||
# self.assertIsNone(serializer.data.get('id', None), 'New instance. `id` should not be set.')
|
# self.assertIsNone(serializer.data.get('id', None), 'New instance. `id` should not be set.')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user