diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index adb6a65b5b..d919cc0022 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1301,9 +1301,10 @@ def build_standard_field(self, field_name, model_field): field_kwargs['queryset'] = model_field.related_model.objects if 'choices' in field_kwargs: - # Fields with choices get coerced into `ChoiceField` - # instead of using their regular typed field. - field_class = self.serializer_choice_field + # Fields with choices default to `ChoiceField`, unless a custom + # `ChoiceField` subclass is already mapped for the model field. + if not issubclass(field_class, self.serializer_choice_field): + field_class = self.serializer_choice_field # Some model fields may introduce kwargs that would not be valid # for the choice field. We need to strip these out. # Eg. models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES) diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index 5ad9cc264c..077e981578 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -369,6 +369,34 @@ class Meta: assert choices_field_with_nonstandard_args.choices assert choices_field_with_nonstandard_args.read_only is False + def test_custom_choice_field_mapping(self): + class CustomModelField(models.CharField): + pass + + class CustomChoiceField(serializers.ChoiceField): + pass + + class CustomChoiceModel(models.Model): + field = CustomModelField( + max_length=10, + choices=COLOR_CHOICES, + ) + + class TestSerializer(serializers.ModelSerializer): + serializer_field_mapping = { + **serializers.ModelSerializer.serializer_field_mapping, + CustomModelField: CustomChoiceField, + } + + class Meta: + model = CustomChoiceModel + fields = ('field',) + + field = TestSerializer().fields['field'] + + assert isinstance(field, CustomChoiceField) + assert list(field.choices) == [choice[0] for choice in COLOR_CHOICES] + def test_non_editable_choice_field(self): class ExampleSerializer(serializers.ModelSerializer): class Meta: