diff --git a/django_setup_configuration/fields.py b/django_setup_configuration/fields.py index a957cca..1826fda 100644 --- a/django_setup_configuration/fields.py +++ b/django_setup_configuration/fields.py @@ -127,6 +127,17 @@ def __init__( else: field_info_creation_kwargs["default"] = inferred_default + # Defaults for fields with choices often do not map neatly onto the consructed + # type used for serialization (e.g. a string) because they may not be a literal + # choices but e.g. an enum/Choices member. Inferring the types of the default + # can be non-trivial (especially if a default factory is involved), and because + # we care about types that can be expressed as simple YAML/JSON scalars, it also + # would not make much sense to add complex types to the annotation. + validate_defaults = False if self.django_field.choices else True + field_info_creation_kwargs["validate_default"] = field_info_creation_kwargs[ + "validate_return" + ] = validate_defaults + return super().__init__(**field_info_creation_kwargs) @staticmethod diff --git a/testapp/models.py b/testapp/models.py index 72a988f..cf73470 100644 --- a/testapp/models.py +++ b/testapp/models.py @@ -25,6 +25,12 @@ class TestModel(models.Model): str_with_choices_and_default = models.CharField( max_length=3, choices=StrChoices.choices, default=StrChoices.bar ) + str_with_choices_and_incorrectly_typed_default = models.CharField( + max_length=3, choices=StrChoices.choices, default=1974 + ) + str_with_choices_and_incorrectly_typed_default_factory = models.CharField( + max_length=3, choices=StrChoices.choices, default=lambda: 1985 + ) str_with_choices_and_blank = models.CharField( max_length=3, choices=StrChoices.choices, blank=True ) diff --git a/tests/test_django_model_ref_field.py b/tests/test_django_model_ref_field.py index 4721feb..9c6bac4 100644 --- a/tests/test_django_model_ref_field.py +++ b/tests/test_django_model_ref_field.py @@ -372,3 +372,18 @@ class Config(ConfigurationModel): assert field.annotation == Literal[1, 8] | Literal[42] assert field.default == 42 assert field.is_required() is False + + +def test_choices_with_incorrectly_typed_default_is_not_validated(): + + class Config(ConfigurationModel): + str_with_choices_and_incorrectly_typed_default = DjangoModelRef( + TestModel, "str_with_choices_and_incorrectly_typed_default" + ) + str_with_choices_and_incorrectly_typed_default_factory = DjangoModelRef( + TestModel, "str_with_choices_and_incorrectly_typed_default_factory" + ) + + config = Config() + assert config.str_with_choices_and_incorrectly_typed_default == 1974 + assert config.str_with_choices_and_incorrectly_typed_default_factory == 1985