diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py index 15c4b91055..d35caca0c7 100644 --- a/rest_framework/utils/field_mapping.py +++ b/rest_framework/utils/field_mapping.py @@ -121,6 +121,9 @@ def get_field_kwargs(field_name, model_field): if model_field.null: kwargs['allow_null'] = True + if model_field.choices: + kwargs['choices'] = model_field.choices + if isinstance(model_field, models.AutoField) or not model_field.editable: # If this field is read-only, then return early. # Further keyword arguments are not valid. @@ -151,9 +154,7 @@ def get_field_kwargs(field_name, model_field): if model_field.allow_folders is not False: kwargs['allow_folders'] = model_field.allow_folders - if model_field.choices: - kwargs['choices'] = model_field.choices - else: + if not model_field.choices: # Ensure that max_value is passed explicitly as a keyword arg, # rather than as a validator. max_value = next(( diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index 60820df4f4..944c1ba278 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -25,6 +25,7 @@ from rest_framework import serializers from rest_framework.compat import postgres_fields +from rest_framework.fields import ChoiceField from .models import NestedForeignKeySource @@ -95,6 +96,7 @@ class FieldOptionsModel(models.Model): class ChoicesModel(models.Model): choices_field_with_nonstandard_args = models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES, verbose_name='A label') + non_editable_choice_field = models.CharField(choices=COLOR_CHOICES, default=COLOR_CHOICES[0][0], editable=False, max_length=5) class Issue3674ParentModel(models.Model): @@ -360,7 +362,23 @@ class Meta: model = ChoicesModel fields = '__all__' - ExampleSerializer() + serializer = ExampleSerializer() + choices_field_with_nonstandard_args = serializer.get_fields()['choices_field_with_nonstandard_args'] + assert isinstance(choices_field_with_nonstandard_args, ChoiceField) + assert choices_field_with_nonstandard_args.choices + assert choices_field_with_nonstandard_args.read_only is False + + def test_non_editable_choice_field(self): + class ExampleSerializer(serializers.ModelSerializer): + class Meta: + model = ChoicesModel + fields = '__all__' + + serializer = ExampleSerializer() + non_editable_choice_field = serializer.get_fields()['non_editable_choice_field'] + assert isinstance(non_editable_choice_field, ChoiceField) + assert non_editable_choice_field.read_only is True + assert non_editable_choice_field.choices class TestDurationFieldMapping(TestCase):