From a639a7c4a436bb1a666032f02354f78bf1242e68 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 30 May 2018 16:38:23 +0200 Subject: [PATCH] Fix DictField.get_value to return `empty` Without this, an empty field is not considered to be empty and then validators might fail, e.g. django.contrib.postgres.validators.RangeMinValueValidator with > E TypeError: '<' not supported between instances of 'NoneType' and 'int' --- rest_framework/fields.py | 9 ++++++++- tests/test_fields.py | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 70c210c16..07bfb96f1 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1708,10 +1708,17 @@ class DictField(Field): self.child.bind(field_name='', parent=self) def get_value(self, dictionary): + if self.field_name not in dictionary: + if getattr(self.root, 'partial', False): + return empty # We override the default field access in order to support # dictionaries in HTML forms. if html.is_html_input(dictionary): - return html.parse_html_dict(dictionary, prefix=self.field_name) + val = dictionary.getlist(self.field_name, {}) + if len(val) > 0: + # Support QueryDict lists in HTML input. + return val + return html.parse_html_list(dictionary, prefix=self.field_name, default=empty) return dictionary.get(self.field_name, empty) def to_internal_value(self, data): diff --git a/tests/test_fields.py b/tests/test_fields.py index 9a1d04979..165641121 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -16,7 +16,7 @@ from django.utils.timezone import activate, deactivate, override, utc import rest_framework from rest_framework import exceptions, serializers from rest_framework.compat import ProhibitNullCharactersValidator -from rest_framework.fields import DjangoImageField, is_simple_callable +from rest_framework.fields import DjangoImageField, empty, is_simple_callable try: import typings @@ -168,6 +168,11 @@ class TestEmpty: output = field.run_validation() assert output is 123 + def test_dictfield_empty(self): + field = serializers.DictField() + field.field_name = 'dict_field' + assert field.get_value(QueryDict()) is empty + class TestSource: def test_source(self):