#34721: ChoiceField/TypedChoiceField: .value() has inconsistent behaviour, 
coercion
not applied.
------------------------+--------------------------------------
     Reporter:  Daniel  |                    Owner:  nobody
         Type:  Bug     |                   Status:  new
    Component:  Forms   |                  Version:  4.2
     Severity:  Normal  |               Resolution:
     Keywords:          |             Triage Stage:  Unreviewed
    Has patch:  0       |      Needs documentation:  0
  Needs tests:  0       |  Patch needs improvement:  0
Easy pickings:  0       |                    UI/UX:  0
------------------------+--------------------------------------
Description changed by Daniel:

Old 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 }}`.

New 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 }}`.

 Ultimately leads to `{% if colour_id == my_form.colour.value %}` never
 being true when the form is bound, even when it should.

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34721#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701896a325d9b-e391b6da-40cc-4cf3-9f53-6a2be481188f-000000%40eu-central-1.amazonses.com.

Reply via email to