Since allow_null=True, the serializer can still validate and partially update even though partial=False #9501
Open
Description
Description:
When using Django’s model and serializer as shown below, the FlowSerializer allows partial updates even when partial=False
, due to allow_null=True
for the flow_id field.
Model:
class Flow(models.Model):
flow_id = models.IntegerField(null=True)
flow_info = models.JSONField()
Serializer:
class FlowSerializer(serializers.ModelSerializer):
flow_id = serializers.IntegerField(allow_null=True, required=False)
class Meta:
model = Flow
fields = "__all__"
Input data:
FlowSerializer(instance, data={"flow_info": {"test":1}})
When the input data does not include the flow_id field, the serializer still passes validation, resulting in a partial update. This behavior is unexpected because partial=True is not used.
Source Code Insight:
The relevant code in the Django REST framework source is:
def get_default(self):
"""
Return the default value to use when validating data if no input
is provided for this field.
If a default has not been set for this field then this will simply
raise `SkipField`, indicating that no value should be set in the
validated data for this field.
"""
if self.default is empty or getattr(self.root, 'partial', False):
# No default, or this is a partial update.
raise SkipField()
Questions:
- Why does the get_default method check getattr(self.root, 'partial', False)?
- Why does the serializer allow validation to pass in non-partial update scenarios, even when not all fields are provided?
- Shouldn’t the serializer require all fields to be provided when partial=False?
This behavior is causing confusion and leads to unintended partial updates. Any insights or clarification on this design choice would be greatly appreciated.
Metadata
Assignees
Labels
No labels