From a6c5cc7dc97f241c899397f2b395fe262fff9346 Mon Sep 17 00:00:00 2001 From: Arek Korbik Date: Sat, 21 May 2016 14:31:35 +0200 Subject: [PATCH] Improve HTML form rendering of choice fields Expose basic value on BoundField instances and use it to improve rendering of choice fields in HTML form output. Fixes #4120, #4121 --- .../rest_framework/horizontal/select.html | 2 +- .../horizontal/select_multiple.html | 2 +- .../rest_framework/inline/select.html | 2 +- .../rest_framework/inline/select_multiple.html | 2 +- .../rest_framework/vertical/select.html | 2 +- .../vertical/select_multiple.html | 2 +- rest_framework/utils/serializer_helpers.py | 18 +++++++++++++----- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/rest_framework/templates/rest_framework/horizontal/select.html b/rest_framework/templates/rest_framework/horizontal/select.html index 1ea5c16e2..5a57cfb1c 100644 --- a/rest_framework/templates/rest_framework/horizontal/select.html +++ b/rest_framework/templates/rest_framework/horizontal/select.html @@ -16,7 +16,7 @@ {% elif select.end_option_group %} {% else %} - + {% endif %} {% endfor %} diff --git a/rest_framework/templates/rest_framework/horizontal/select_multiple.html b/rest_framework/templates/rest_framework/horizontal/select_multiple.html index b00a63fbe..bb30996ed 100644 --- a/rest_framework/templates/rest_framework/horizontal/select_multiple.html +++ b/rest_framework/templates/rest_framework/horizontal/select_multiple.html @@ -16,7 +16,7 @@ {% elif select.end_option_group %} {% else %} - + {% endif %} {% empty %} diff --git a/rest_framework/templates/rest_framework/inline/select.html b/rest_framework/templates/rest_framework/inline/select.html index 99f10ae71..2796dba24 100644 --- a/rest_framework/templates/rest_framework/inline/select.html +++ b/rest_framework/templates/rest_framework/inline/select.html @@ -15,7 +15,7 @@ {% elif select.end_option_group %} {% else %} - + {% endif %} {% endfor %} diff --git a/rest_framework/templates/rest_framework/inline/select_multiple.html b/rest_framework/templates/rest_framework/inline/select_multiple.html index 1c0e96b3c..a9bd08be1 100644 --- a/rest_framework/templates/rest_framework/inline/select_multiple.html +++ b/rest_framework/templates/rest_framework/inline/select_multiple.html @@ -15,7 +15,7 @@ {% elif select.end_option_group %} {% else %} - + {% endif %} {% empty %} diff --git a/rest_framework/templates/rest_framework/vertical/select.html b/rest_framework/templates/rest_framework/vertical/select.html index 973efb679..dceaa5c9b 100644 --- a/rest_framework/templates/rest_framework/vertical/select.html +++ b/rest_framework/templates/rest_framework/vertical/select.html @@ -15,7 +15,7 @@ {% elif select.end_option_group %} {% else %} - + {% endif %} {% endfor %} diff --git a/rest_framework/templates/rest_framework/vertical/select_multiple.html b/rest_framework/templates/rest_framework/vertical/select_multiple.html index dcbee2eda..a04cfbfd6 100644 --- a/rest_framework/templates/rest_framework/vertical/select_multiple.html +++ b/rest_framework/templates/rest_framework/vertical/select_multiple.html @@ -15,7 +15,7 @@ {% elif select.end_option_group %} {% else %} - + {% endif %} {% empty %} diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index cfaeb25e8..75bcf5c49 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -8,6 +8,10 @@ from django.utils.encoding import force_text from rest_framework.compat import unicode_to_repr +# A singleton helper value to detect unset keyword arguments +unset = object() + + class ReturnDict(OrderedDict): """ Return object from `serialier.data` for the `Serializer` class. @@ -58,10 +62,11 @@ class BoundField(object): providing an API similar to Django forms and form fields. """ - def __init__(self, field, value, errors, prefix=''): + def __init__(self, field, value, errors, prefix='', basic_value=unset): self._field = field self._prefix = prefix self.value = value + self.basic_value = value if basic_value is unset else basic_value self.errors = errors self.name = prefix + self.field_name @@ -79,7 +84,8 @@ class BoundField(object): def as_form_field(self): value = '' if (self.value is None or self.value is False) else force_text(self.value) - return self.__class__(self._field, value, self.errors, self._prefix) + return self.__class__(self._field, value, self.errors, self._prefix, + self.basic_value) class NestedBoundField(BoundField): @@ -89,10 +95,11 @@ class NestedBoundField(BoundField): `BoundField` that is used for serializer fields. """ - def __init__(self, field, value, errors, prefix=''): + def __init__(self, field, value, errors, prefix='', basic_value=unset): if value is None or value is '': value = {} - super(NestedBoundField, self).__init__(field, value, errors, prefix) + super(NestedBoundField, self).__init__(field, value, errors, prefix, + basic_value) def __iter__(self): for field in self.fields.values(): @@ -113,7 +120,8 @@ class NestedBoundField(BoundField): values[key] = value else: values[key] = '' if (value is None or value is False) else force_text(value) - return self.__class__(self._field, values, self.errors, self._prefix) + return self.__class__(self._field, values, self.errors, self._prefix, + self.basic_value) class BindingDict(collections.MutableMapping):