Skip to content

Fix DictField partial HTML omission handling#9906

Open
Sebastianhayashi wants to merge 3 commits intoencode:mainfrom
Sebastianhayashi:codex/fix-6234
Open

Fix DictField partial HTML omission handling#9906
Sebastianhayashi wants to merge 3 commits intoencode:mainfrom
Sebastianhayashi:codex/fix-6234

Conversation

@Sebastianhayashi
Copy link

Summary

Fix DictField handling for HTML form input on partial updates.

When the field is omitted in multipart/HTML input, DictField.get_value() currently returns {} and the serializer incorrectly treats the field as provided. This change returns empty for partial updates when parsed HTML dict input is empty, so omitted fields stay omitted.

Reproduction

from django.http import QueryDict
from rest_framework import serializers

class S(serializers.Serializer):
    field_name = serializers.DictField(required=False)

s = S(data=QueryDict(''), partial=True)
s.is_valid()
print(s.validated_data)  # before: {'field_name': {}}, after: {}

Changes

  • rest_framework/fields.py
    • In DictField.get_value(), for HTML input:
      • parse value via parse_html_dict
      • if value is empty and self.root.partial is true, return empty
  • tests/test_fields.py
    • Added regression test: test_partial_update_does_not_include_missing_html_dict_field

Validation

pytest -q \
  tests/test_fields.py::TestDictField::test_partial_update_does_not_include_missing_html_dict_field \
  tests/test_fields.py::TestDictField::test_allow_empty_disallowed \
  tests/test_fields.py::TestMultipleChoiceField::test_against_partial_and_full_updates

Result: 3 passed

Related to #6234.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Django REST framework’s DictField behavior for HTML/multipart inputs during partial updates so that an omitted dict field is treated as “missing” (sentinel empty) rather than an empty dict, preventing it from incorrectly appearing in validated_data.

Changes:

  • Updated DictField.get_value() to return empty when HTML parsing yields no keys during partial updates.
  • Added a regression test covering the partial-update omission case for HTML input.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
rest_framework/fields.py Treats empty parsed HTML dict input as omitted (empty) when partial=True.
tests/test_fields.py Adds regression test ensuring omitted HTML dict fields do not appear in validated_data on partial updates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if html.is_html_input(dictionary):
return html.parse_html_dict(dictionary, prefix=self.field_name)
value = html.parse_html_dict(dictionary, prefix=self.field_name)
if not value and getattr(self.root, 'partial', False):
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DictField.get_value() still returns an empty dict for omitted HTML/multipart input when partial=False. That means omitted DictFields can bypass the normal empty sentinel handling (e.g., required=True won’t raise “required”, and required=False fields can incorrectly show up in validated_data as {}). Consider matching Serializer.get_value()/ListField.get_value() behavior by returning empty whenever parse_html_dict(...) is empty (e.g., ... or empty), not only on partial updates.

Suggested change
if not value and getattr(self.root, 'partial', False):
if not value:

Copilot uses AI. Check for mistakes.
Comment on lines +2532 to 2533


Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new regression test covers partial updates, but the underlying omission behavior for HTML dict input can also affect full updates and required=True fields (omitted field being treated as {} instead of missing). Add a complementary test case for partial=False (and ideally required=True) to lock in the expected behavior once DictField.get_value() is adjusted.

Suggested change
def test_full_update_missing_required_html_dict_field_is_error(self):
class TestSerializer(serializers.Serializer):
field_name = serializers.DictField(required=True)
serializer = TestSerializer(data=QueryDict(''), partial=False)
assert not serializer.is_valid()
assert 'field_name' in serializer.errors

Copilot uses AI. Check for mistakes.
Comment on lines +2525 to +2531
def test_partial_update_does_not_include_missing_html_dict_field(self):
class TestSerializer(serializers.Serializer):
field_name = serializers.DictField(required=False)

serializer = TestSerializer(data=QueryDict(''), partial=True)
assert serializer.is_valid()
assert 'field_name' not in serializer.validated_data
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to increate test coverage... This test passes on the main branch, but breaks here:

    def test_partial_update_can_clear_html_dict_field(self):
        class TestSerializer(serializers.Serializer):
            field_name = serializers.DictField(required=False)

        serializer = TestSerializer(data=QueryDict('field_name='), partial=True)
        assert serializer.is_valid()
        assert 'field_name' in serializer.validated_data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants