mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 11:04:02 +03:00
Make set_value a method within Serializer
(#8001)
* Make set_value a static method for Serializers As an alternative to #7671, let the method be overridden if needed. As the function is only used for serializers, it has a better place in the Serializer class. * Set `set_value` as an object (non-static) method * Add tests for set_value() These tests follow the examples given in the method.
This commit is contained in:
parent
a25aac7d67
commit
d252d22343
|
@ -113,27 +113,6 @@ def get_attribute(instance, attrs):
|
|||
return instance
|
||||
|
||||
|
||||
def set_value(dictionary, keys, value):
|
||||
"""
|
||||
Similar to Python's built in `dictionary[key] = value`,
|
||||
but takes a list of nested keys instead of a single key.
|
||||
|
||||
set_value({'a': 1}, [], {'b': 2}) -> {'a': 1, 'b': 2}
|
||||
set_value({'a': 1}, ['x'], 2) -> {'a': 1, 'x': 2}
|
||||
set_value({'a': 1}, ['x', 'y'], 2) -> {'a': 1, 'x': {'y': 2}}
|
||||
"""
|
||||
if not keys:
|
||||
dictionary.update(value)
|
||||
return
|
||||
|
||||
for key in keys[:-1]:
|
||||
if key not in dictionary:
|
||||
dictionary[key] = {}
|
||||
dictionary = dictionary[key]
|
||||
|
||||
dictionary[keys[-1]] = value
|
||||
|
||||
|
||||
def to_choices_dict(choices):
|
||||
"""
|
||||
Convert choices into key/value dicts.
|
||||
|
|
|
@ -28,7 +28,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from rest_framework.compat import postgres_fields
|
||||
from rest_framework.exceptions import ErrorDetail, ValidationError
|
||||
from rest_framework.fields import get_error_detail, set_value
|
||||
from rest_framework.fields import get_error_detail
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.utils import html, model_meta, representation
|
||||
from rest_framework.utils.field_mapping import (
|
||||
|
@ -346,6 +346,26 @@ class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
|
|||
'invalid': _('Invalid data. Expected a dictionary, but got {datatype}.')
|
||||
}
|
||||
|
||||
def set_value(self, dictionary, keys, value):
|
||||
"""
|
||||
Similar to Python's built in `dictionary[key] = value`,
|
||||
but takes a list of nested keys instead of a single key.
|
||||
|
||||
set_value({'a': 1}, [], {'b': 2}) -> {'a': 1, 'b': 2}
|
||||
set_value({'a': 1}, ['x'], 2) -> {'a': 1, 'x': 2}
|
||||
set_value({'a': 1}, ['x', 'y'], 2) -> {'a': 1, 'x': {'y': 2}}
|
||||
"""
|
||||
if not keys:
|
||||
dictionary.update(value)
|
||||
return
|
||||
|
||||
for key in keys[:-1]:
|
||||
if key not in dictionary:
|
||||
dictionary[key] = {}
|
||||
dictionary = dictionary[key]
|
||||
|
||||
dictionary[keys[-1]] = value
|
||||
|
||||
@cached_property
|
||||
def fields(self):
|
||||
"""
|
||||
|
@ -492,7 +512,7 @@ class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
|
|||
except SkipField:
|
||||
pass
|
||||
else:
|
||||
set_value(ret, field.source_attrs, validated_value)
|
||||
self.set_value(ret, field.source_attrs, validated_value)
|
||||
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
|
|
@ -762,3 +762,24 @@ class Test8301Regression:
|
|||
|
||||
assert (s.data | {}).__class__ == s.data.__class__
|
||||
assert ({} | s.data).__class__ == s.data.__class__
|
||||
|
||||
|
||||
class TestSetValueMethod:
|
||||
# Serializer.set_value() modifies the first parameter in-place.
|
||||
|
||||
s = serializers.Serializer()
|
||||
|
||||
def test_no_keys(self):
|
||||
ret = {'a': 1}
|
||||
self.s.set_value(ret, [], {'b': 2})
|
||||
assert ret == {'a': 1, 'b': 2}
|
||||
|
||||
def test_one_key(self):
|
||||
ret = {'a': 1}
|
||||
self.s.set_value(ret, ['x'], 2)
|
||||
assert ret == {'a': 1, 'x': 2}
|
||||
|
||||
def test_nested_key(self):
|
||||
ret = {'a': 1}
|
||||
self.s.set_value(ret, ['x', 'y'], 2)
|
||||
assert ret == {'a': 1, 'x': {'y': 2}}
|
||||
|
|
Loading…
Reference in New Issue
Block a user