Django Rest Framework 3 requires field behavior

I read the change log for drf3, but its still not clear to me. I used to have the following serializer:

class TestSerializer(serializers.Serializer): att1= serializers.CharField() att2= serializers.CharField() att3= serializers.CharField(required=False) 

And when I was passing the object only with att1 and att2 values, it worked fine, no errors and no attribute in the output. But now, if I do not pas att3, I got an error

Got KeyError when trying to get the value for the att3 field in the att3 serializer.
The serializer field may be incorrectly named and does not match the attribute or key in the EasyDict instance.
The exception source code was: att3 '.

But according to the release notes:

required = False: the value should not be present at the input

So the code seems valid for me or I don’t understand something.

  data = TestSerializer(s.get_results()).data 

Where get_results is an instance of EasyDict with missing att3:

 class EasyDict(dict): def __init__(self, d=None, **kwargs): if d is None: d = {} if kwargs: d.update(**kwargs) for k, v in d.items(): setattr(self, k, v) # Class attributes for k in self.__class__.__dict__.keys(): if not (k.startswith('__') and k.endswith('__')): setattr(self, k, getattr(self, k)) def __setattr__(self, name, value): if isinstance(value, (list, tuple)): value = [self.__class__(x) if isinstance(x, dict) else x for x in value] else: value = self.__class__(value) if isinstance(value, dict) else value super(EasyDict, self).__setattr__(name, value) self[name] = value 

It worked fine in drf2, but got this error after upgrading to drf3.

+5
source share
2 answers

The Django REST Framework uses serializers to serialize (output) and deserialize (input) data.

It's hard to say if you are serializing or deserializing your data in your case, but you will find problems with both, so I will give you an answer for both cases.


When deserializing data, you must pass the data for deserialization using the data keyword argument and (optionally) the instance to update using the instance keyword argument.

 serializer = TestSerializer(data=s.get_results()) if serializer.is_valid(): data = serializer.data 

This should work as expected, up to calling .data in the serializer. This is because the .data call will serialize the data object again, based on a temporary instance, which you'll learn below, still remains a problem.

It is important to note that when deserializing data, the required=False parameter will prevent the Django REST Framework from requiring this field to be present.


When serializing data, you need to pass a complete representation of the object using the instance keyword argument, which is also the first positional argument. The Django REST Framework expects the object to be passed will have all the fields you request, even if they are null ( None ) or empty. The required=False argument does nothing, because we serialize the data. Therefore, you need to make sure that the dictionary (or comparable object) is passed with all the keys that are required for the serializer.

There is a special case when an object is deserialized and then serialized using the same object. In this case, the base object that was created must still have an optional field, even if the input did not provide it.

+3
source

I find the same thing, look in the code, and also read the document, I find:

http://www.django-rest-framework.org/api-guide/serializers/#inspecting-a-modelserializer

Serializing Multiple Objects

Serialize a set of queries or a list of objects instead of a single object. For example, you must pass the many = True flag when creating an instance to the serializer.

My code for 2.x was:

CollectionSerializer (collections) .data p>

change to:

CollectionSerializer (collections, many = True) .data p>

The problem is resolved.

0
source

Source: https://habr.com/ru/post/1209703/


All Articles