Fix for ModelSerializer ChoiceField with nonstandard args. Closes #3126.

This commit is contained in:
Tom Christie 2015-07-16 15:46:27 +01:00
parent 713333d354
commit e14391e041
2 changed files with 27 additions and 0 deletions

View File

@ -1033,6 +1033,19 @@ class ModelSerializer(Serializer):
# Fields with choices get coerced into `ChoiceField` # Fields with choices get coerced into `ChoiceField`
# instead of using their regular typed field. # instead of using their regular typed field.
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)
valid_kwargs = set((
'read_only', 'write_only',
'required', 'default', 'initial', 'source',
'label', 'help_text', 'style',
'error_messages', 'validators', 'allow_null', 'allow_blank',
'choices'
))
for key in list(field_kwargs.keys()):
if key not in valid_kwargs:
field_kwargs.pop(key)
if not issubclass(field_class, ModelField): if not issubclass(field_class, ModelField):
# `model_field` is only valid for the fallback case of # `model_field` is only valid for the fallback case of

View File

@ -7,6 +7,8 @@ an appropriate set of serializer fields for each case.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import decimal
import django import django
import pytest import pytest
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
@ -70,6 +72,7 @@ class RegularFieldsModel(models.Model):
COLOR_CHOICES = (('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')) COLOR_CHOICES = (('red', 'Red'), ('blue', 'Blue'), ('green', 'Green'))
DECIMAL_CHOICES = (('low', decimal.Decimal('0.1')), ('medium', decimal.Decimal('0.5')), ('high', decimal.Decimal('0.9')))
class FieldOptionsModel(models.Model): class FieldOptionsModel(models.Model):
@ -82,6 +85,10 @@ class FieldOptionsModel(models.Model):
choices_field = models.CharField(max_length=100, choices=COLOR_CHOICES) choices_field = models.CharField(max_length=100, choices=COLOR_CHOICES)
class MappingForChoicesWithNonStandardArgs(models.Model):
choices_field_with_nonstandard_args = models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES)
class TestModelSerializer(TestCase): class TestModelSerializer(TestCase):
def test_create_method(self): def test_create_method(self):
class TestSerializer(serializers.ModelSerializer): class TestSerializer(serializers.ModelSerializer):
@ -307,6 +314,13 @@ class TestRegularFieldMappings(TestCase):
ChildSerializer().fields ChildSerializer().fields
def test_choices_with_nonstandard_args(self):
class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = MappingForChoicesWithNonStandardArgs
ExampleSerializer()
@pytest.mark.skipif(django.VERSION < (1, 8), @pytest.mark.skipif(django.VERSION < (1, 8),
reason='DurationField is only available for django1.8+') reason='DurationField is only available for django1.8+')