diff --git a/drf_spectacular/plumbing.py b/drf_spectacular/plumbing.py index 07db4b15..cc3ddf7a 100644 --- a/drf_spectacular/plumbing.py +++ b/drf_spectacular/plumbing.py @@ -420,8 +420,13 @@ def build_parameter_type( def build_choice_field(field) -> _SchemaType: choices = list(OrderedDict.fromkeys(field.choices)) # preserve order and remove duplicates - if all(isinstance(choice, bool) for choice in choices): - type: Optional[str] = 'boolean' + if field.allow_blank and '' not in choices: + choices.append('') + + if not choices: + type = None + elif all(isinstance(choice, bool) for choice in choices): + type = 'boolean' elif all(isinstance(choice, int) for choice in choices): type = 'integer' elif all(isinstance(choice, (int, float, Decimal)) for choice in choices): # `number` includes `integer` @@ -432,8 +437,6 @@ def build_choice_field(field) -> _SchemaType: else: type = None - if field.allow_blank and '' not in choices: - choices.append('') if field.allow_null and None not in choices: choices.append(None) diff --git a/tests/test_plumbing.py b/tests/test_plumbing.py index 4e917cd3..cbdafcfe 100644 --- a/tests/test_plumbing.py +++ b/tests/test_plumbing.py @@ -398,6 +398,30 @@ def test_choicefield_choices_enum(): assert schema['enum'] == ['bluepill', 'redpill', '', None] assert 'type' not in schema + schema = build_choice_field(serializers.ChoiceField( + choices=[1, 2], allow_blank=True + )) + assert schema['enum'] == [1, 2, ''] + assert 'type' not in schema + + +def test_choicefield_empty_choices(): + schema = build_choice_field(serializers.ChoiceField(choices=[])) + assert schema['enum'] == [] + assert 'type' not in schema + + schema = build_choice_field(serializers.ChoiceField(choices=[], allow_null=True)) + assert schema['enum'] == [None] + assert 'type' not in schema + + schema = build_choice_field(serializers.ChoiceField(choices=[], allow_blank=True)) + assert schema['enum'] == [''] + assert schema['type'] == 'string' + + schema = build_choice_field(serializers.ChoiceField(choices=[], allow_blank=True, allow_null=True)) + assert schema['enum'] == ['', None] + assert schema['type'] == 'string' + def test_safe_ref(): schema = build_basic_type(str)