Validate PATCH requests without erasing omitted values

A PATCH request can omit a field, send null or send an empty string. Those inputs carry different intent. If an update function treats every missing key as None, editing a display name can accidentally erase the user's biography.
Omission preserves the existing value; an allowed null or blank is an explicit change.
Let the serializer preserve absence
This self-contained validation example uses Django REST Framework fields and a synthetic dictionary as the record:
from rest_framework import serializers
class ProfilePatch(serializers.Serializer):
display_name = serializers.CharField(
required=False, allow_blank=False
)
bio = serializers.CharField(
required=False, allow_blank=True, allow_null=True
)
record = {"display_name": "Sam", "bio": "Writes Python"}
serializer = ProfilePatch(
data={"display_name": "Sam Lee"}, partial=True
)
serializer.is_valid(raise_exception=True)
updated = {**record, **serializer.validated_data}
assert updated["display_name"] == "Sam Lee"
assert updated["bio"] == "Writes Python"
The omitted bio key never enters validated_data. Sending bio=null would include a null value because this field explicitly allows it. Sending an empty string would preserve an empty string. The product should decide whether those latter states need to remain distinct.
This fragment demonstrates input semantics, not a complete persistence layer. With a ModelSerializer, review its update behavior and model nullability. A serializer accepting null for a non-null database column creates a second failure later in the request.
Test the three payloads separately
Use one request that changes only display_name, another that sends bio=null and a third that sends bio="". Verify both the API response and the saved record after each request. Also send an empty display name and confirm the validation error is attached to the correct field.
Avoid replacing the instance with request.data or assigning every possible attribute through dict.get(). Both patterns can erase the distinction between omitted and explicitly cleared input. Use validated values and a known update policy.
Nested objects need another decision. Does sending one nested field merge with the existing object or replace the entire nested value? PATCH by itself does not define your application's custom JSON merge semantics. Document the behavior and add a fixture where one sibling nested field is omitted.
An empty PATCH object should have a declared outcome too: either preserve the record unchanged or return an intentional validation response.
These API boundaries are related to the forms and operational records in Nirogidhara. DRF's serializer documentation describes partial updates and field validation.