diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py index 29005f6b7c..b8817d9766 100644 --- a/rest_framework/utils/field_mapping.py +++ b/rest_framework/utils/field_mapping.py @@ -123,18 +123,70 @@ def get_field_kwargs(field_name, model_field): kwargs['allow_folders'] = model_field.allow_folders if model_field.choices: - # If this model field contains choices, then return early. - # Further keyword arguments are not valid. kwargs['choices'] = model_field.choices - return kwargs - - # Our decimal validation is handled in the field code, not validator code. - # (In Django 1.9+ this differs from previous style) - if isinstance(model_field, models.DecimalField) and DecimalValidator: - validator_kwarg = [ - validator for validator in validator_kwarg - if not isinstance(validator, DecimalValidator) - ] + else: + # Ensure that max_value is passed explicitly as a keyword arg, + # rather than as a validator. + max_value = next(( + validator.limit_value for validator in validator_kwarg + if isinstance(validator, validators.MaxValueValidator) + ), None) + if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): + kwargs['max_value'] = max_value + validator_kwarg = [ + validator for validator in validator_kwarg + if not isinstance(validator, validators.MaxValueValidator) + ] + + # Ensure that max_value is passed explicitly as a keyword arg, + # rather than as a validator. + min_value = next(( + validator.limit_value for validator in validator_kwarg + if isinstance(validator, validators.MinValueValidator) + ), None) + if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): + kwargs['min_value'] = min_value + validator_kwarg = [ + validator for validator in validator_kwarg + if not isinstance(validator, validators.MinValueValidator) + ] + + # URLField does not need to include the URLValidator argument, + # as it is explicitly added in. + if isinstance(model_field, models.URLField): + validator_kwarg = [ + validator for validator in validator_kwarg + if not isinstance(validator, validators.URLValidator) + ] + + # EmailField does not need to include the validate_email argument, + # as it is explicitly added in. + if isinstance(model_field, models.EmailField): + validator_kwarg = [ + validator for validator in validator_kwarg + if validator is not validators.validate_email + ] + + # SlugField do not need to include the 'validate_slug' argument, + if isinstance(model_field, models.SlugField): + validator_kwarg = [ + validator for validator in validator_kwarg + if validator is not validators.validate_slug + ] + + # IPAddressField do not need to include the 'validate_ipv46_address' argument, + if isinstance(model_field, models.GenericIPAddressField): + validator_kwarg = [ + validator for validator in validator_kwarg + if validator is not validators.validate_ipv46_address + ] + # Our decimal validation is handled in the field code, not validator code. + # (In Django 1.9+ this differs from previous style) + if isinstance(model_field, models.DecimalField) and DecimalValidator: + validator_kwarg = [ + validator for validator in validator_kwarg + if not isinstance(validator, DecimalValidator) + ] # Ensure that max_length is passed explicitly as a keyword arg, # rather than as a validator. @@ -160,62 +212,6 @@ def get_field_kwargs(field_name, model_field): if not isinstance(validator, validators.MinLengthValidator) ] - # Ensure that max_value is passed explicitly as a keyword arg, - # rather than as a validator. - max_value = next(( - validator.limit_value for validator in validator_kwarg - if isinstance(validator, validators.MaxValueValidator) - ), None) - if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): - kwargs['max_value'] = max_value - validator_kwarg = [ - validator for validator in validator_kwarg - if not isinstance(validator, validators.MaxValueValidator) - ] - - # Ensure that max_value is passed explicitly as a keyword arg, - # rather than as a validator. - min_value = next(( - validator.limit_value for validator in validator_kwarg - if isinstance(validator, validators.MinValueValidator) - ), None) - if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): - kwargs['min_value'] = min_value - validator_kwarg = [ - validator for validator in validator_kwarg - if not isinstance(validator, validators.MinValueValidator) - ] - - # URLField does not need to include the URLValidator argument, - # as it is explicitly added in. - if isinstance(model_field, models.URLField): - validator_kwarg = [ - validator for validator in validator_kwarg - if not isinstance(validator, validators.URLValidator) - ] - - # EmailField does not need to include the validate_email argument, - # as it is explicitly added in. - if isinstance(model_field, models.EmailField): - validator_kwarg = [ - validator for validator in validator_kwarg - if validator is not validators.validate_email - ] - - # SlugField do not need to include the 'validate_slug' argument, - if isinstance(model_field, models.SlugField): - validator_kwarg = [ - validator for validator in validator_kwarg - if validator is not validators.validate_slug - ] - - # IPAddressField do not need to include the 'validate_ipv46_address' argument, - if isinstance(model_field, models.GenericIPAddressField): - validator_kwarg = [ - validator for validator in validator_kwarg - if validator is not validators.validate_ipv46_address - ] - if getattr(model_field, 'unique', False): unique_error_message = model_field.error_messages.get('unique', None) if unique_error_message: diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index cfa671125d..08fc3b42d5 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -99,6 +99,15 @@ class Issue3674ChildModel(models.Model): value = models.CharField(primary_key=True, max_length=64) +class UniqueChoiceModel(models.Model): + CHOICES = ( + ('choice1', 'choice 1'), + ('choice2', 'choice 1'), + ) + + name = models.CharField(max_length=254, unique=True, choices=CHOICES) + + class TestModelSerializer(TestCase): def test_create_method(self): class TestSerializer(serializers.ModelSerializer): @@ -1080,3 +1089,16 @@ class Meta: with pytest.raises(AssertionError) as cm: TestSerializer(obj).fields cm.match(r'readonly_fields') + + +class Test5004UniqueChoiceField(TestCase): + def test_unique_choice_field(self): + class TestUniqueChoiceSerializer(serializers.ModelSerializer): + class Meta: + model = UniqueChoiceModel + fields = '__all__' + + UniqueChoiceModel.objects.create(name='choice1') + serializer = TestUniqueChoiceSerializer(data={'name': 'choice1'}) + assert not serializer.is_valid() + assert serializer.errors == {'name': ['unique choice model with this name already exists.']} 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