﻿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
28176	Expose real (i.e. not converted to string) value in widget option context	Moritz Sichert	nobody	"In #28075 `option.value` was changed to always be converted to a string before passing it to the template. I have a use case that doesn't work anymore because of this. I have this form:

{{{#!python
from django.forms import Form, RadioSelect, TypedChoiceField


CHOICES = [
    (1, 'INFO'),
    (2, 'WARNING'),
    (3, 'SUCCESS'),
    (4, 'DANGER'),
]

CHOICES_DICT = {name: value for value, name in CHOICES}


class RadioSelectWithIcons(RadioSelect):
    template_name = 'radio_select_with_icons.html'

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['choices'] = CHOICES_DICT
        return context


class MyForm(Form):
    foo = TypedChoiceField(
        coerce=int,
        choices=CHOICES,
        widget=RadioSelectWithIcons
    )
}}}

and the following template (`radio_select_with_icons.html`):

{{{#!htmldjango
{% for _, options, _ in widget.optgroups %}
  {% for option in options %}
    <label class=""btn btn-default{% if option.selected %} active{% endif %}"">
      <input type=""radio"" name=""{{ widget.name }}"" value=""{{ option.value }}""{% if option.selected %} checked=""checked""{% endif %}>
      {{ option.label }}
      {% if option.value == choices.INFO %}
        <span class=""fa fa-info-circle text-info""></span>
      {% elif option.value == choices.WARNING %}
        <span class=""fa fa-times-circle text-warning""></span>
      {% elif option.value == choices.SUCCESS %}
        <span class=""fa fa-check-circle text-success""></span>
      {% elif option.value == choices.DANGER %}
        <span class=""fa fa-exclamation-circle text-danger""></span>
      {% endif %}
    </label>
  {% endfor %}
{% endfor %}
}}}
Now, when I render this form, none of the `<span class=""fa ...""></span>` are displayed. This is because `option.value` is a string and `choices.X` are integers so the equality will obviously always be false.

I can see two solutions to this that don't involve changing code in Django:

1.: Convert the integers in the `choices` to strings as well. I don't think this is a sensible solution since I ''know'' that both values are supposed to be integers but instead compare their string representations. This also becomes a problem if the string version of the value is ambiguous, e.g. translated strings.
2.: Pass the css classes I use in the `<span>` as context from the widget. I also think, that this is a bad approach, because I want to separate python code from display logic. This also wouldn't work for more complex things that don't change just a css class.


I think there is a good, simple solution to this:  In `ChoiceWidget.create_option()` the returned context should also contain the un-stringified value. Maybe even rename the current `value` to `str_value` and store the actual value in `value`.

What do you think?"	New feature	closed	Forms	dev	Normal	fixed		Preston Timmons	Accepted	1	0	0	0	0	0
