Reputation: 17621
I have read a changelog for drf3 but its still unclear for me. Previously i have following serializer:
class TestSerializer(serializers.Serializer):
att1= serializers.CharField()
att2= serializers.CharField()
att3= serializers.CharField(required=False)
And when i was passing object with only att1 and att2 values in it - it was working fine, no errors, no attribute in the output. But now if i don't pas att3 i got error
Got KeyError when attempting to get a value for field
att3
on serializerTestSerializer
.
The serializer field might be named incorrectly and not match any attribute or key on theEasyDict
instance.
Original exception text was: att3'.
But according to release notes:
required=False: The value does not need to be present in the input
So the code seems valid for me or i don't understand something.
data = TestSerializer(s.get_results()).data
Where get_results 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 was working perfectly fine in drf2, but got this error after upgrading to drf3.
Upvotes: 5
Views: 5083
Reputation: 1919
I hit the same thing, look inside the code and also read the document, I find:
http://www.django-rest-framework.org/api-guide/serializers/#inspecting-a-modelserializer
Serializing multiple objects
To serialize a queryset or list of objects instead of a single object instance, you should pass the many=True flag when instantiating the serializer.
My code for 2.x was:
CollectionSerializer(collections).data
change to:
CollectionSerializer(collections, many=True).data
Problem solved.
Upvotes: 0
Reputation: 41719
Django REST Framework uses serializers for both serializing (output) and deserializing (input) data.
It's difficult to tell if you are serializing or deserializing your data in your case, but you will find issues with both, so I'll give you an answer for both cases.
When deserializing data, you should pass in the data to deserialize in using the data
keyword argument, and (optionally) the instance to update with the instance
keyword argument.
serializer = TestSerializer(data=s.get_results())
if serializer.is_valid():
data = serializer.data
This should work as expected, up until you call .data
on the serializer. This is because calling .data
will then serialize the data object again, based on the temporary instance, which you'll learn below is still an issue.
It is important to note that when deserializing data, the required=False
parameter will prevent Django REST Framework from requiring that the field is present.
When serializing data, you need to pass a full object representation in using the instance
keyword argument, which is also the first positional argument. Django REST Framework expects that the object that is passed in will have all of the fields that you are requesting, even if they are null
(None
) or blank. The required=False
argument does nothing here because we are serialzing data. So you need to ensure that the dictionary (or comparable object) is passed in with all of the keys that the serializer requires.
There is a special case though, when an object is being deserialized and then serialized using the same object. In this case, the underlying object that has been created must still have the optional field, even if the input did not provide it.
Upvotes: 5