This commit is contained in:
Arek Korbik 2016-08-08 10:18:08 +00:00 committed by GitHub
commit 4a636252f6
13 changed files with 165 additions and 31 deletions

View File

@ -328,9 +328,6 @@ class HTMLFormRenderer(BaseRenderer):
style['template_pack'] = parent_style.get('template_pack', self.template_pack)
style['renderer'] = self
# Get a clone of the field with text-only value representation.
field = field.as_form_field()
if style.get('input_type') == 'datetime-local' and isinstance(field.value, six.text_type):
field.value = field.value.rstrip('Z')

View File

@ -6,7 +6,7 @@
{% endif %}
<div class="col-sm-10">
<input name="{{ field.name }}" {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.value %}value="{{ field.value }}"{% endif %}>
<input name="{{ field.name }}" {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.string_value %}value="{{ field.string_value }}"{% endif %}>
{% if field.errors %}
{% for error in field.errors %}

View File

@ -8,7 +8,7 @@
<div class="col-sm-10">
<select class="form-control" name="{{ field.name }}">
{% if field.allow_null or field.allow_blank %}
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
<option value="" {% if not field.string_value %}selected{% endif %}>--------</option>
{% endif %}
{% for select in field.iter_options %}
{% if select.start_option_group %}

View File

@ -6,7 +6,7 @@
{% endif %}
<div class="col-sm-10">
<textarea name="{{ field.name }}" class="form-control" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if style.rows %}rows="{{ style.rows }}"{% endif %}>{% if field.value %}{{ field.value }}{% endif %}</textarea>
<textarea name="{{ field.name }}" class="form-control" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if style.rows %}rows="{{ style.rows }}"{% endif %}>{% if field.string_value %}{{ field.string_value }}{% endif %}</textarea>
{% if field.errors %}
{% for error in field.errors %}

View File

@ -5,5 +5,5 @@
</label>
{% endif %}
<input name="{{ field.name }}" {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.value %}value="{{ field.value }}"{% endif %}>
<input name="{{ field.name }}" {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.string_value %}value="{{ field.string_value }}"{% endif %}>
</div>

View File

@ -7,7 +7,7 @@
<select class="form-control" name="{{ field.name }}">
{% if field.allow_null or field.allow_blank %}
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
<option value="" {% if not field.string_value %}selected{% endif %}>--------</option>
{% endif %}
{% for select in field.iter_options %}
{% if select.start_option_group %}

View File

@ -5,5 +5,5 @@
</label>
{% endif %}
<input name="{{ field.name }}" type="text" class="form-control" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.value %}value="{{ field.value }}"{% endif %}>
<input name="{{ field.name }}" type="text" class="form-control" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.string_value %}value="{{ field.string_value }}"{% endif %}>
</div>

View File

@ -3,7 +3,7 @@
<label {% if style.hide_label %}class="sr-only"{% endif %}>{{ field.label }}</label>
{% endif %}
<input name="{{ field.name }}" {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.value %}value="{{ field.value }}"{% endif %}>
<input name="{{ field.name }}" {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.string_value %}value="{{ field.string_value }}"{% endif %}>
{% if field.errors %}
{% for error in field.errors %}

View File

@ -7,7 +7,7 @@
<select class="form-control" name="{{ field.name }}">
{% if field.allow_null or field.allow_blank %}
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
<option value="" {% if not field.string_value %}selected{% endif %}>--------</option>
{% endif %}
{% for select in field.iter_options %}
{% if select.start_option_group %}

View File

@ -5,7 +5,7 @@
</label>
{% endif %}
<textarea name="{{ field.name }}" class="form-control" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if style.rows %}rows="{{ style.rows }}"{% endif %}>{% if field.value %}{{ field.value }}{% endif %}</textarea>
<textarea name="{{ field.name }}" class="form-control" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if style.rows %}rows="{{ style.rows }}"{% endif %}>{% if field.string_value %}{{ field.string_value }}{% endif %}</textarea>
{% if field.errors %}
{% for error in field.errors %}<span class="help-block">{{ error }}</span>{% endfor %}

View File

@ -72,15 +72,17 @@ class BoundField(object):
def _proxy_class(self):
return self._field.__class__
@property
def string_value(self):
if self.value is None or self.value is False:
return ''
return force_text(self.value)
def __repr__(self):
return unicode_to_repr('<%s value=%s errors=%s>' % (
self.__class__.__name__, self.value, self.errors
))
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)
class NestedBoundField(BoundField):
"""
@ -106,15 +108,6 @@ class NestedBoundField(BoundField):
return NestedBoundField(field, value, error, prefix=self.name + '.')
return BoundField(field, value, error, prefix=self.name + '.')
def as_form_field(self):
values = {}
for key, value in self.value.items():
if isinstance(value, (list, dict)):
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)
class BindingDict(collections.MutableMapping):
"""

View File

@ -45,15 +45,15 @@ class TestSimpleBoundField:
assert serializer['amount'].errors is None
assert serializer['amount'].name == 'amount'
def test_as_form_fields(self):
def test_string_value(self):
class ExampleSerializer(serializers.Serializer):
bool_field = serializers.BooleanField()
null_field = serializers.IntegerField(allow_null=True)
serializer = ExampleSerializer(data={'bool_field': False, 'null_field': None})
assert serializer.is_valid()
assert serializer['bool_field'].as_form_field().value == ''
assert serializer['null_field'].as_form_field().value == ''
assert serializer['bool_field'].string_value == ''
assert serializer['null_field'].string_value == ''
class TestNestedBoundField:
@ -78,7 +78,7 @@ class TestNestedBoundField:
assert serializer['nested']['amount'].errors is None
assert serializer['nested']['amount'].name == 'nested.amount'
def test_as_form_fields(self):
def test_string_value(self):
class Nested(serializers.Serializer):
bool_field = serializers.BooleanField()
null_field = serializers.IntegerField(allow_null=True)
@ -88,8 +88,8 @@ class TestNestedBoundField:
serializer = ExampleSerializer(data={'nested': {'bool_field': False, 'null_field': None}})
assert serializer.is_valid()
assert serializer['nested']['bool_field'].as_form_field().value == ''
assert serializer['nested']['null_field'].as_form_field().value == ''
assert serializer['nested']['bool_field'].string_value == ''
assert serializer['nested']['null_field'].string_value == ''
def test_rendering_nested_fields_with_none_value(self):
from rest_framework.renderers import HTMLFormRenderer

View File

@ -481,3 +481,147 @@ class TestHTMLFormRenderer(TestCase):
result = renderer.render(self.serializer.data, None, {})
self.assertIsInstance(result, SafeText)
class TestChoiceFieldHTMLFormRenderer(TestCase):
"""
Test rendering ChoiceField with HTMLFormRenderer.
"""
def setUp(self):
choices = ((1, 'Option1'), (2, 'Option2'), (12, 'Option12'))
class TestSerializer(serializers.Serializer):
test_field = serializers.ChoiceField(choices=choices,
initial=2)
self.TestSerializer = TestSerializer
self.renderer = HTMLFormRenderer()
def test_render_initial_option(self):
serializer = self.TestSerializer()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertInHTML('<option value="2" selected>Option2</option>',
result)
self.assertInHTML('<option value="1">Option1</option>', result)
self.assertInHTML('<option value="12">Option12</option>', result)
def test_render_selected_option(self):
serializer = self.TestSerializer(data={'test_field': '12'})
serializer.is_valid()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertInHTML('<option value="12" selected>Option12</option>',
result)
self.assertInHTML('<option value="1">Option1</option>', result)
self.assertInHTML('<option value="2">Option2</option>', result)
class TestMultipleChoiceFieldHTMLFormRenderer(TestCase):
"""
Test rendering MultipleChoiceField with HTMLFormRenderer.
"""
def setUp(self):
self.renderer = HTMLFormRenderer()
def test_render_selected_option_with_string_option_ids(self):
choices = (('1', 'Option1'), ('2', 'Option2'), ('12', 'Option12'),
('}', 'OptionBrace'))
class TestSerializer(serializers.Serializer):
test_field = serializers.MultipleChoiceField(choices=choices)
serializer = TestSerializer(data={'test_field': ['12']})
serializer.is_valid()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertInHTML('<option value="12" selected>Option12</option>',
result)
self.assertInHTML('<option value="1">Option1</option>', result)
self.assertInHTML('<option value="2">Option2</option>', result)
self.assertInHTML('<option value="}">OptionBrace</option>', result)
def test_render_selected_option_with_integer_option_ids(self):
choices = ((1, 'Option1'), (2, 'Option2'), (12, 'Option12'))
class TestSerializer(serializers.Serializer):
test_field = serializers.MultipleChoiceField(choices=choices)
serializer = TestSerializer(data={'test_field': ['12']})
serializer.is_valid()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertInHTML('<option value="12" selected>Option12</option>',
result)
self.assertInHTML('<option value="1">Option1</option>', result)
self.assertInHTML('<option value="2">Option2</option>', result)
class TestIntegerFieldHTMLFormRenderer(TestCase):
"""
Test rendering IntegerField with HTMLFormRenderer.
"""
def setUp(self):
class TestSerializer(serializers.Serializer):
test_field = serializers.IntegerField()
self.TestSerializer = TestSerializer
self.renderer = HTMLFormRenderer()
def test_render_zero(self):
serializer = self.TestSerializer(data={'test_field': '0'})
serializer.is_valid()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertIsNotNone(re.search(r'<input .*value="0"', result, re.S))
class TestFloatFieldHTMLFormRenderer(TestCase):
"""
Test rendering FloatField with HTMLFormRenderer.
"""
def setUp(self):
class TestSerializer(serializers.Serializer):
test_field = serializers.FloatField()
self.TestSerializer = TestSerializer
self.renderer = HTMLFormRenderer()
def test_render_zero(self):
serializer = self.TestSerializer(data={'test_field': '0.0'})
serializer.is_valid()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertIsNotNone(re.search(r'<input .*value="0\.0"', result, re.S))
@override_settings(LANGUAGE_CODE='pl')
def test_render_with_comma_locale(self):
serializer = self.TestSerializer(data={'test_field': '1.5'})
serializer.is_valid()
result = self.renderer.render(serializer.data)
self.assertIsInstance(result, SafeText)
self.assertIsNotNone(re.search(r'<input .*value="1\.5"', result, re.S))