-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Description
Affected Version: 3.14.0
Link to Code: rest_framework/serializers.py#L928
Documentation Link: Partial Updates
Problem:
The update method in Django Rest Framework's serializers appears to ignore the partial flag, resulting in full saves instead of partial updates as expected. This behavior deviates from the documented functionality.
Steps to Reproduce:
Create a serializer with partial=True.
Attempt to update a model instance with only a subset of fields provided.
Observe that all fields in the instance are updated instead of just the provided ones.
Proof of Concept (PoC):
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["bio", "public_username"]
user = User.objects.get(pk=123)
data = {
"bio": "new bio",
"public_username": "new public username",
}
serializer = UserSerializer(user, data=data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()Expected Behavior:
With the partial=True flag set, only fields provided in the serializer's data should be updated in the database, as documented.
Actual Behavior:
Despite setting partial=True, all fields in the instance are updated upon calling serializer.save(), including those not listed in the serializer's fields, such as password and is_superuser.
Proposed Fix:
A potential fix involves modifying the update method to conditionally use update_fields based on the partial flag. Here's a proposed change:
if self.partial:
instance.save(update_fields=validated_data.keys())
else:
instance.save()Additional Notes:
This issue impacts applications relying on partial updates, potentially leading to unintended modifications of instance's attributes, which may lead to unexpected bugs, race conditions etc.
Environment:
Django==4.2.9
djangorestframework==3.14.0
Python: 3.11