I have a ModelForm that I'm rendering in the template with django-widget-tweaks. I have a ChoiceField select that prints out something like this:
<select>
<option value="object.id">object.name</option>
</select>
But for Javascript manipulation purposes, I need the following:
<select>
<option value="object.id" class="object.otherPropery">object.name</option>
</select>
django-widget-tweaks has an add_class function, but it only adds a class to the select box, not the contained options.
I have also tried rolling my own select box:
<select>
{% for object in form.object_field %}
<option value="{{ object.id }}" class="{{ object.otherProperty }}">{{ object.name }}</option>
{% endfor %}
</select>
But when the form does not validate and errors are returned, the option the user had selected previously gets reset back to the default (first) option (this does happen with django-widget-tweaks).
I have also tried overriding the render_option
and render_options
fields of the Select widget, but the additional properties of the object are not being passed to those functions.
I feel like there's a simple solution for what I'm trying to do. Any help would be much appreciated!
You can try this.
render_option
has been removed from Django 1.11 onwards. This is what I did to achieve this. A little bit of digging and this seems straightforward. Works with Django 2.0+The form:
The output which I needed is as:
I think there are problems with adding classes or anything else to option elements. I know the applies for CSS for certain, see this other post for example: Can we add class attribute in option element? I think the same might apply to manipulating it with JavaScript.
It might be a little tricky, but maybe in the template make it write out some JavaScript that maps the {{ object.id }} to the {{ object.otherProperty }}, so you have access to the value that way.
I guess you can do something like this (note the 'if' tag):
Although the if condition might not result in a true result when it should, if the
object.id
is a integer because thevalue
would always be a string for a already submitted form (all the values in the POST/GET query data are strings). But if the value comes from the 'initial_data' it would be integer.For such cases you may update your 'if' tag as follows:
Making the final code as follows: