I have the below in one of my viewset classes:
serializer = ResponsesSerializer(data=queryset, many=True)
serializer.is_valid(raise_exception=True)
validated_data = serializer.validated_data
response = Response(validated_data, status=status.HTTP_200_OK)
return response
For testing purposes, queryset
is the below list of objects that is being passed to my ResponsesSerializer
, where only the first object has a record
key:
queryset = [
{
"C_Ethnicity.r1": 0,
"C_Ethnicity.r2": 0,
"EaseOfFind.r1": 0,
"EaseOfFind.r2": 1,
"Leg.r1": 0,
"Leg.r2": 0,
"record": 17
},
{
"C_Ethnicity.r1": 0,
"C_Ethnicity.r2": 0,
"EaseOfFind.r1": 0,
"EaseOfFind.r2": 1,
"Leg.r1": 1,
"Leg.r2": 0,
},
{
"C_Ethnicity.r1": 0,
"C_Ethnicity.r2": 0,
"EaseOfFind.r1": 0,
"EaseOfFind.r2": 1,
"Leg.r1": 1,
"Leg.r2": 0,
}
]
In the response, the serializer expectedly raises a validation error for the last two objects without a record
key, but I don't know why the first object is then empty:
[
{},
{
"non_field_errors": [
"Missing 'record' key in dictionary."
]
},
{
"non_field_errors": [
"Missing 'record' key in dictionary."
]
}
]
This is the ResponsesSerializer
:
class ResponsesSerializer(serializers.Serializer):
def to_internal_value(self, data):
return data
def validate(self, data):
if 'record' not in data:
raise serializers.ValidationError("Missing 'record' key in dictionary.")
return data
I'm new to serializers, and in this case I just want to add validation criteria that each object in the list can be tested for, i.e having a record
key or a certain length of items, and ignoring any other keys.
but I don't know why the first object is then empty.
The serializer validates all elements in the list, and only is valid in case all items are valid.
If one or more items are invalid, it returns the errors. It does that with a list of dictionaries where for each item in the given data, it has an item in the error list. This makes sense since one probably wants to know for which item which errors apply. So the first dictionary contains errors for the first item.
Since the first item thus contains no errors, it is an empty dictionary, meaning that the first item is valid, but the rest is not.
It probably makes a lot of sense to only insert data if all items match, since one usually wants operations to be atomically: either all succeed (together) or none at all.
I just want to add validation criteria that each object in the list can be tested for, i.e having a record key or a certain length of items.
Typically you don't implement validate
yourself. You add fields to the serializer, like:
class ResponsesSerializer(serializers.Serializer):
record = serializer.CharField(required=True)
this will then check if there is indeed a record
field that is a string.
or a certain length of items.
In that case you can work with a ListSerializer
, which is essentially what a many=True
does. You can easily construct this with:
serializer = ResponsesSerializer(many=True, min_length=5, max_length=5)
this will require that there are exactly five items in the request.