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
This commit is contained in:
Arek Korbik 2016-05-21 14:31:35 +02:00
parent f742452d46
commit a6c5cc7dc9
7 changed files with 19 additions and 11 deletions

View File

@ -16,7 +16,7 @@
{% elif select.end_option_group %} {% elif select.end_option_group %}
</optgroup> </optgroup>
{% else %} {% else %}
<option value="{{ select.value }}" {% if select.value == field.value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option> <option value="{{ select.value }}" {% if select.value == field.basic_value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</select> </select>

View File

@ -16,7 +16,7 @@
{% elif select.end_option_group %} {% elif select.end_option_group %}
</optgroup> </optgroup>
{% else %} {% else %}
<option value="{{ select.value }}" {% if select.value in field.value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option> <option value="{{ select.value }}" {% if select.value in field.basic_value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
{% endif %} {% endif %}
{% empty %} {% empty %}
<option>{{ no_items }}</option> <option>{{ no_items }}</option>

View File

@ -15,7 +15,7 @@
{% elif select.end_option_group %} {% elif select.end_option_group %}
</optgroup> </optgroup>
{% else %} {% else %}
<option value="{{ select.value }}" {% if select.value == field.value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option> <option value="{{ select.value }}" {% if select.value == field.basic_value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</select> </select>

View File

@ -15,7 +15,7 @@
{% elif select.end_option_group %} {% elif select.end_option_group %}
</optgroup> </optgroup>
{% else %} {% else %}
<option value="{{ select.value }}" {% if select.value in field.value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option> <option value="{{ select.value }}" {% if select.value in field.basic_value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
{% endif %} {% endif %}
{% empty %} {% empty %}
<option>{{ no_items }}</option> <option>{{ no_items }}</option>

View File

@ -15,7 +15,7 @@
{% elif select.end_option_group %} {% elif select.end_option_group %}
</optgroup> </optgroup>
{% else %} {% else %}
<option value="{{ select.value }}" {% if select.value == field.value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option> <option value="{{ select.value }}" {% if select.value == field.basic_value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</select> </select>

View File

@ -15,7 +15,7 @@
{% elif select.end_option_group %} {% elif select.end_option_group %}
</optgroup> </optgroup>
{% else %} {% else %}
<option value="{{ select.value }}" {% if select.value in field.value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option> <option value="{{ select.value }}" {% if select.value in field.basic_value %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
{% endif %} {% endif %}
{% empty %} {% empty %}
<option>{{ no_items }}</option> <option>{{ no_items }}</option>

View File

@ -8,6 +8,10 @@ from django.utils.encoding import force_text
from rest_framework.compat import unicode_to_repr from rest_framework.compat import unicode_to_repr
# A singleton helper value to detect unset keyword arguments
unset = object()
class ReturnDict(OrderedDict): class ReturnDict(OrderedDict):
""" """
Return object from `serialier.data` for the `Serializer` class. 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. 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._field = field
self._prefix = prefix self._prefix = prefix
self.value = value self.value = value
self.basic_value = value if basic_value is unset else basic_value
self.errors = errors self.errors = errors
self.name = prefix + self.field_name self.name = prefix + self.field_name
@ -79,7 +84,8 @@ class BoundField(object):
def as_form_field(self): def as_form_field(self):
value = '' if (self.value is None or self.value is False) else force_text(self.value) 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): class NestedBoundField(BoundField):
@ -89,10 +95,11 @@ class NestedBoundField(BoundField):
`BoundField` that is used for serializer fields. `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 '': if value is None or value is '':
value = {} value = {}
super(NestedBoundField, self).__init__(field, value, errors, prefix) super(NestedBoundField, self).__init__(field, value, errors, prefix,
basic_value)
def __iter__(self): def __iter__(self):
for field in self.fields.values(): for field in self.fields.values():
@ -113,7 +120,8 @@ class NestedBoundField(BoundField):
values[key] = value values[key] = value
else: else:
values[key] = '' if (value is None or value is False) else force_text(value) 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): class BindingDict(collections.MutableMapping):