﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34156	TypedChoiceField not compatible with IntegerChoices	Yoshio Hasegawa	nobody	"Coercion always fails when using IntegerChoices with a TypedChoiceField in a Django form.

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)
}}}"	Bug	closed	Forms	4.1	Normal	invalid	Form, TypedChoiceField, IntegerChoices, Coercion		Unreviewed	0	0	0	0	0	0
