#28176: Expose real (i.e. not converted to string) value in widget option
context
------------------------------------------+------------------------
Reporter: Moritz Sichert | Owner: nobody
Type: New feature | Status: new
Component: Forms | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------+------------------------
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?
--
Ticket URL: <https://code.djangoproject.com/ticket/28176>
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 post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/050.791fb6060b8b7de0d5b02afaa2dddf1c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.