Description
Checklist
- Raised initially as discussion #...
- This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
- I have reduced the issue to the simplest possible case.
The Documentation states the following about the required
keyword argument:
"Normally an error will be raised if a field is not supplied during deserialization. Set to false if this field is not required to be present during deserialization.
Setting this to False also allows the object attribute or dictionary key to be omitted from output when serializing the instance. If the key is not present it will simply not be included in the output representation. "
However this doesn't work correctly with django.http.QueryDict. When passing a QueryDict to the Serializer, the not required fields are not omitted in the output but instead are set to False.
Affected Version:
django_rest_framework <= 3.12
found when upgrading from 3.11 to latest version
A Code Example
from django.http import QueryDict
from rest_framework import serializers
data_dict = {'required': True}
data_querydict = QueryDict('required=True')
class TestSerializer(serializers.Serializer):
required = serializers.BooleanField(required=True)
param = serializers.BooleanField(required=False)
serializer1 = TestSerializer(data=data_dict)
serializer1.is_valid()
serializer2 = TestSerializer(data=data_querydict)
serializer2.is_valid()
print(f"Serialized Dict: {serializer1.validated_data}")
print(f"Serialized QueryDict: {serializer2.validated_data}")
if serializer1.validated_data != serializer2.validated_data:
print("There is a Bug")
When executing this Example you will see that:
serializer1.validated_data == OrderedDict([('required', True)])
while serializer2.validated_data == OrderedDict([('required', True), ('param', False)])
.
This diverging behaviour is not present in other types of Field (Tested myself: CharField, IntegerField)
This is potentially an API breaking change
Possible Workaround
As Described here
from rest_framework import fields, serializers
class DefaultEmptyBooleanField(fields.BooleanField):
default_empty_html = fields.empty
class MySerializer(serializers.Serializer):
boolean_field = DefaultEmptyBooleanField(required=False)
Expected Behavior
not required fields are omitted in the output for both Dict and QueryDict