Skip to content

Since allow_null=True, the serializer can still validate and partially update even though partial=False #9501

Open
@fbozhang

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions