94
I’ve been struggling with this problem today and found the solution. Yes, you can iterate over options of the select tag directly in template. Here’s how to do it in template:
<select id="id_customer" name="customer">
{% for x, y in form.fields.customer.choices %}
<option value="{{ x }}"{% if form.fields.customer.value == x %} selected{% endif %}>{{ y }}</option>
{% endfor %}
</select>
In this case I have a customer
field in the form which has choices set up as follows:
class SomeForm(forms.Form):
customer = forms.ChoiceField(label=u'Customer')
def __init__(self, *args, **kwargs):
super(SomeForm, self).__init__(*args, **kwargs)
self.fields['customer'].choices = [(e.id, e.customer) for e in Customers.objects.all()]
30
Got it to work with:
<select name="myselect" class="i-can-add-my-own-attrs-now" id="id_myselect">
{% for id, name in form.myselect.field.choices %}
<option value="{{ id }}">{{ name }}</option>
{% endfor %}
</select>
BUT REALLY, a better way to do this is with django-widget-tweaks:
{% load widget_tweaks %}
{{ form.myselect|add_class:"i-can-haz-custom-classes-easily" }}
Doing it with django-widget-tweaks will also set the default ‘selected=”selected”‘ for you, which is super nice!
- [Django]-Django Management Command Argument
- [Django]-405 "Method POST is not allowed" in Django REST framework
- [Django]-Django pass object to include
9
I do this way:
<select id="id_construction_type" name="construction_type" class="form-control input-md">
{% for value, key in form_urban.fields.construction_type.choices %}
<option value="{{ value }}"{% if form_urban.initial.construction_type == value %} selected {% endif %}>
{{ key }}
</option>
{% endfor %}
</select>
- [Django]-Django-rest-framework: api versioning
- [Django]-Django: allow line break from textarea input
- [Django]-Django URLs TypeError: view must be a callable or a list/tuple in the case of include()
4
This is a cleaner solution, you can set the attributes using a custom Widget. This way you don’t have to render the field manually:
class CustomSelectWidget(forms.Select):
def create_option(self, name, value, *args, **kwargs):
option = super().create_option(name, value, *args, **kwargs)
if value:
instance = self.choices.queryset.get(pk=value) # get instance
option['attrs']['custom_attr'] = instance.field_name # set option attribute
return option
class SomeForm(forms.ModelForm):
some_field = forms.ModelChoiceField(
queryset=SomeModel.objects.all(),
widget=CustomSelectWidget
)
- [Django]-Django Passing Custom Form Parameters to Formset
- [Django]-How to run cloned Django project?
- [Django]-Python NameError: name 'include' is not defined
1
I’ve run into this issue several times and wanted to add an additional situation where you are using Django filters and setting choices that are related to a FieldFilter you’ve defined inside the FilterSet class.
class CustomFilter(django_filters.FilterSet):
your_field = django_filters.CharFilter(
field_name='your_field',
lookup_expr='iexact',
widget=forms.Select(
choices=[(x, x) for x in some_list_of_choices]
)
)
The other solutions, rely on a .choices
attribute on the field
class but they did not work for me. Instead I iterated through the your_field
attr on the Form
associated with the FilterSet
.
This allows you to easily set your own default and assign any desired classes to the select element.
<select name="your_field">
<option value="" selected>Your Field</option>
{% for option in filter.form.your_field %}
{{ option }}
{% endfor %}
</select>
- [Django]-What's the difference between select_related and prefetch_related in Django ORM?
- [Django]-"No installed app with label 'admin'" running Django migration. The app is installed correctly
- [Django]-Django admin: how to sort by one of the custom list_display fields that has no database field
0
With radio buttons in your template use.
<table>
{% for x,y in form.fields.Customer.choices %}
<tr>
<td><input id="id_Customer_{{x}}" {% if form.fields.Customer.value == x %}checked="checked"{% endif %} name="Customer" type="radio" value="{{x}}" /></td>
<td>{{ y }}</td>
</tr>
{% endfor %}
</table>
- [Django]-Default filter in Django model
- [Django]-Change Django ModelChoiceField to show users' full names rather than usernames
- [Django]-Django: Assigning variables in template