I've just updated from Django 1.10 to 1.11.1.
In my template new_house_edit.html
I have the following:
{{ form.rating }}
models.py
contain the following:
class NewHouse(models.Model):
rating = models.IntegerField(choices=(
(1, "1"),
(2, "2"),
(3, "3"),
(4, "4"),
(5, "5"),
),
default=3
)
In forms.py
I used to have the following:
class HorizontalRadioRenderer(forms.RadioSelect.renderer):
def render(self):
return mark_safe(u'\n'.join([u'%s\n' % w for w in self]))
class NewHouseForm(forms.ModelForm):
class Meta:
model = NewHouse
fields = (
'rating',)
widgets={
"rating": forms.RadioSelect(renderer=HorizontalRadioRenderer),
}
Which gave the following error AttributeError: type object 'RadioSelect' has no attribute 'renderer'.
I tried to solve it by doing this which is not working:
class HorizontalRadioSelect(forms.RadioSelect):
template_name = 'new_house_edit'
class NewHouseForm(forms.ModelForm):
class Meta:
model = NewHouse
fields = (
'rating',)
widgets={
"rating": "rating": forms.ChoiceField(widget=HorizontalRadioSelect, choices=(1, 2, 3, 4, 5)),
}
I now get the error AttributeError: 'ChoiceField' object has no attribute 'use_required_attribute'
. Can anyone help me fix this?
In your second code snippet you pass form field object to widgets dict instead of widget object. So correct code look like:
class HorizontalRadioSelect(forms.RadioSelect):
template_name = 'horizontal_select.html'
class NewHouseForm(forms.ModelForm):
class Meta:
model = NewHouse
fields = (
'rating',)
widgets={
"rating": HorizontalRadioSelect()
}
In your app directory create templates folder and add horizontal_select.html with following html.
{% with id=widget.attrs.id %}
<ul{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>
{% for group, options, index in widget.optgroups %}
{% if group %}
<li>{{ group }}
<ul{% if id %} id="{{ id }}_{{ index }}"{% endif %}>
{% endif %}
{% for option in options %}
<li style="display: inline-block">{% include option.template_name with widget=option %}</li>
{% endfor %}
{% if group %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
{% endwith %}
I know this is quite an old question but having spent some time today trying the different methods in various threads (after upgrading from 1.8 to 1.11) here is my solution.
For each radio group, define the following in the template (where "radio_list" is the name of the field):
{% for radio in radio_list %}
{{ radio }}
{% endfor %}
This is it at its simplest. Easy eh? You can basically apply any styling you want. It's all in the documentation in the RadioSelect section.
The moral of this little tale? Read the docs. Django is probably the best-documented app I have ever worked with. If I had done it earlier it would have saved me a lot of wasted time today when I could have been doing something more interesting.
Hope this helps someone.
First, ChoiceField is not a widget - it is a Form Field.
So, change your form,
class NewHouseForm(forms.ModelForm):
CHOICES = ((1, "1"),
(2, "2"),
(3, "3"),
(4, "4"),
(5, "5"))
rating = forms.ChoiceField(choices=CHOICES,
widget=forms.RadioSelect(attrs={'class': 'radio-inline'}),
)
class Meta:
model = NewHouse
fields = (
'rating',)
Then in your customised radio-select template_name
should be the path to the template which is you are using.
If the template resides under your app_level "templates" subdirectory or in your project-level "templates" sub-directory, you could just do like below.
class HorizontalRadioSelect(forms.RadioSelect):
template_name = 'new_house_edit.html'
If its under another subdirectory under the "templates" sub-directory then you need to specify the path to the template.
Django as default check for templates in "templates" sub-directory in each apps of your project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With