mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-31 07:57:55 +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