-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Fix DictField HTML input returning empty dict for missing fields #9891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,7 +66,7 @@ def parse_html_list(dictionary, prefix='', default=None): | |
| return [ret[item] for item in sorted(ret)] if ret else default | ||
|
|
||
|
|
||
| def parse_html_dict(dictionary, prefix=''): | ||
| def parse_html_dict(dictionary, prefix='', default=None): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks consistent with what we do for parsing html list 👍🏻 : |
||
| """ | ||
| Used to support dictionary values in HTML forms. | ||
|
|
||
|
|
@@ -81,6 +81,9 @@ def parse_html_dict(dictionary, prefix=''): | |
| 'email': 'example@example.com' | ||
| } | ||
| } | ||
|
|
||
| :returns a MultiValueDict of the parsed data, or the value specified in | ||
| ``default`` if the dict field was not present in the input | ||
| """ | ||
| ret = MultiValueDict() | ||
| regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix)) | ||
|
|
@@ -92,4 +95,4 @@ def parse_html_dict(dictionary, prefix=''): | |
| value = dictionary.getlist(field) | ||
| ret.setlist(key, value) | ||
|
|
||
| return ret | ||
| return ret if ret else default | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2496,6 +2496,56 @@ def test_allow_empty_disallowed(self): | |||||
|
|
||||||
| assert exc_info.value.detail == ['This dictionary may not be empty.'] | ||||||
|
|
||||||
| def test_querydict_dict_input(self): | ||||||
| """ | ||||||
| DictField should correctly parse HTML form (QueryDict) input | ||||||
| with dot-separated keys. | ||||||
| """ | ||||||
| class TestSerializer(serializers.Serializer): | ||||||
| data = serializers.DictField(child=serializers.CharField()) | ||||||
|
|
||||||
| serializer = TestSerializer(data=QueryDict('data.a=1&data.b=2')) | ||||||
| assert serializer.is_valid() | ||||||
|
||||||
| assert serializer.is_valid() | |
| assert serializer.is_valid(), serializer.errors |
Some for the other assert serializer.is_valid() in the other tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, updated all three to assert serializer.is_valid(), serializer.errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't a better default be an empty dict here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this but it actually breaks
test_querydict_dict_input. Whento_internal_valuegets called, the data is already a MultiValueDict with parsed keys.parse_html_dictwith no prefix looks for dot-prefixed keys which don't match, sodefault={}would lose the already-parsed data. Keepingdefault=dataas a fallback preserves it correctly. Happy to discuss further though!