Opened 2 years ago
Last modified 2 years ago
#34721 closed Bug
ChoiceField/TypedChoiceField: .value() has inconsistent behaviour, coercion not applied. — at Initial Version
| Reported by: | Daniel | Owned by: | nobody |
|---|---|---|---|
| Component: | Forms | Version: | 4.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Given a form like
# forms.py
class MyForm(Form):
colour = ChoiceField(
choices=[(0, "Red"), (1, "Green"), (2, "Blue"), (3, "Yellow")],
initial=0,
widget=HiddenInput(),
required=True,
)
# views.py
def my_view(request):
my_form = MyForm(request.POST or None)
...
return render(request,"template.html", { "my_form": my_form })
and a template like
{% for colour_id, colour in my_form.fields.colour.choices %}
{{ colour }}: {% if colour_id == my_form.colour.value %}selected{% else %}not selected{% endif %}
{% endfor %}
I find inconsistent behaviour in the return type of my_form["colour"], or {{ my_form.colour.value }} respectively.
my_form.fields["colour"].choices, and {{ my_form.fields.colour.choices }} correctly return the list of tuples assigned to the choices= parameter of the ChoiceField, retaining their types. Hence, colour_id and colour are of type int and string respectively.
If the form is unbound and the fields initial= value is used, then my_form["colour"], and {{ my_form.colour.value }} return the initial value of 0 as type int.
If the form is bound, then my_form["colour"], and {{ my_form.colour.value }} return the selected choice as type str.
I would expect that all, my_form.fields["colour"].choices and {{ my_form.fields.colour.choices }} and my_form["colour"] and {{ my_form.colour.value }} would return the values as the same type.
Changing ChoiceField(...) to TypedChoiceField(..., coerce=int) does only affect my_form.cleaned_data["colour"], but neither of my_form.fields["colour"].choices,{{ my_form.fields.colour.choices }}, or my_form["colour"], or{{ my_form.colour.value }}.