Skip to content

Commit 54a18a4

Browse files
committed
Merge pull request #2239 from jpadilla/allow-blank-choicefield
Add allow_blank for ChoiceField #2184
2 parents cae19f8 + afe7ed9 commit 54a18a4

File tree

7 files changed

+30
-10
lines changed

7 files changed

+30
-10
lines changed

rest_framework/fields.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,9 +958,14 @@ def __init__(self, choices, **kwargs):
958958
(six.text_type(key), key) for key in self.choices.keys()
959959
])
960960

961+
self.allow_blank = kwargs.pop('allow_blank', False)
962+
961963
super(ChoiceField, self).__init__(**kwargs)
962964

963965
def to_internal_value(self, data):
966+
if data == '' and self.allow_blank:
967+
return ''
968+
964969
try:
965970
return self.choice_strings_to_values[six.text_type(data)]
966971
except KeyError:

rest_framework/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ def get_fields(self):
942942
# `ModelField`, which is used when no other typed field
943943
# matched to the model field.
944944
kwargs.pop('model_field', None)
945-
if not issubclass(field_cls, CharField):
945+
if not issubclass(field_cls, CharField) and not issubclass(field_cls, ChoiceField):
946946
# `allow_blank` is only valid for textual fields.
947947
kwargs.pop('allow_blank', None)
948948

rest_framework/templates/rest_framework/horizontal/select.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{% endif %}
55
<div class="col-sm-10">
66
<select class="form-control" name="{{ field.name }}">
7-
{% if field.allow_null %}
7+
{% if field.allow_null or field.allow_blank %}
88
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
99
{% endif %}
1010
{% for key, text in field.choices.items %}

rest_framework/templates/rest_framework/inline/select.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<label class="sr-only">{{ field.label }}</label>
44
{% endif %}
55
<select class="form-control" name="{{ field.name }}">
6-
{% if field.allow_null %}
6+
{% if field.allow_null or field.allow_blank %}
77
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
88
{% endif %}
99
{% for key, text in field.choices.items %}

rest_framework/templates/rest_framework/vertical/select.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<label {% if style.hide_label %}class="sr-only"{% endif %}>{{ field.label }}</label>
44
{% endif %}
55
<select class="form-control" name="{{ field.name }}">
6-
{% if field.allow_null %}
6+
{% if field.allow_null or field.allow_blank %}
77
<option value="" {% if not field.value %}selected{% endif %}>--------</option>
88
{% endif %}
99
{% for key, text in field.choices.items %}

rest_framework/utils/field_mapping.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,18 @@ def get_field_kwargs(field_name, model_field):
9191
if model_field.has_default() or model_field.blank or model_field.null:
9292
kwargs['required'] = False
9393

94-
if model_field.flatchoices:
95-
# If this model field contains choices, then return early.
96-
# Further keyword arguments are not valid.
97-
kwargs['choices'] = model_field.flatchoices
98-
return kwargs
99-
10094
if model_field.null and not isinstance(model_field, models.NullBooleanField):
10195
kwargs['allow_null'] = True
10296

10397
if model_field.blank:
10498
kwargs['allow_blank'] = True
10599

100+
if model_field.flatchoices:
101+
# If this model field contains choices, then return early.
102+
# Further keyword arguments are not valid.
103+
kwargs['choices'] = model_field.flatchoices
104+
return kwargs
105+
106106
# Ensure that max_length is passed explicitly as a keyword arg,
107107
# rather than as a validator.
108108
max_length = getattr(model_field, 'max_length', None)

tests/test_fields.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,21 @@ class TestChoiceField(FieldValues):
804804
]
805805
)
806806

807+
def test_allow_blank(self):
808+
"""
809+
If `allow_blank=True` then '' is a valid input.
810+
"""
811+
field = serializers.ChoiceField(
812+
allow_blank=True,
813+
choices=[
814+
('poor', 'Poor quality'),
815+
('medium', 'Medium quality'),
816+
('good', 'Good quality'),
817+
]
818+
)
819+
output = field.run_validation('')
820+
assert output is ''
821+
807822

808823
class TestChoiceFieldWithType(FieldValues):
809824
"""

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy