When a value is cleaned in a TypedChoiceField, the inherited ChoiceField's
`to_python()` method will return the value casted as a string. This means
that when coercion with an IntegerChoices object is attempted, it will
always fail as IntegerChoices will expect an int type when instantiated.
=== Example ===
{{{#!python
class SomeIntegerChoice(models.IntegerChoices):
VAL_2350 = (2350, "value 2350")
VAL_4100 = (4100, "value 4100")
VAL_8760 = (8760, "value 8760")
}}}
{{{#!python
form.fields["Integer_choice"] = forms.TypedChoiceField(
required=required,
choices=SomeIntegerChoice.choices,
coerce=SomeIntegerChoice,
)
}}}
This field will never pass validation since `ChoiceField` (inherited by
`TypedChoiceField`) has a `to_python()` method that casts the provided
value as a string:
{{{#!python
# class ChoiceField:
# ...
def to_python(self, value):
"""Return a string."""
if value in self.empty_values:
return ""
return str(value)
}}}
To explain further... `ChoiceField.to_python()` will be called when
`TypedChoiceField` attempts to `clean()` a value. After the value is
cleaned, it is coerced using the provided class definition via the
`coerce` property.
Here is example code from Django to show how this happens:
{{{#!python
# class TypedChoiceField:
# ...
def _coerce(self, value):
"""
Validate that the value can be coerced to the right type (if not
empty).
"""
if value == self.empty_value or value in self.empty_values:
return self.empty_value
try:
value = self.coerce(value)
except (ValueError, TypeError, ValidationError):
raise ValidationError(
self.error_messages["invalid_choice"],
code="invalid_choice",
params={"value": value},
)
return value
def clean(self, value):
value = super().clean(value)
return self._coerce(value)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34156>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* resolution: => invalid
Comment:
As far as I'm aware, it's an issue in your code. For `IntegerChoices` you
should pass `coerce=int` and everything works fine.
--
Ticket URL: <https://code.djangoproject.com/ticket/34156#comment:1>