Align radio buttons horizontally in django forms
HI
I want to align the radio buttons horizontally. By default django forms displays in vertical format.
feature_type = forms.TypedChoiceField(choices = formfields.FeatureType, widget = forms.RadioSelect)
Is there any special parameter that we can pass for radio buttons alignment?
Thanks in advance
Thats the behavior of the RadioField
. If you want it rendered horizontally, create a horizontal renderer, like something as follows:
from django.utils.safestring import mark_safe
class HorizontalRadioRenderer(forms.RadioSelect.renderer):
def render(self):
return mark_safe(u'\n'.join([u'%s\n' % w for w in self]))
class ApprovalForm(forms.Form):
approval = forms.ChoiceField(choices=APPROVAL_CHOICES,
initial=0,
widget=forms.RadioSelect(renderer=HorizontalRadioRenderer),
)
Another way out is to changing the style of ul->li list to display:inline-block. You can do something like that
<style>
ul#youelementId li{
display: inline-block;
}
</style>
hope this would help next reader.
I've come up with an alternative solution. If you are using bootstrap to render your forms, you can add the .form-check-inline class to the input and the field will display horizontally. Listed below is code that shows what I'm describing. I hope this helps someone from reinventing the wheel. Thanks for reading. Take care and have a good day.
feature_type = forms.MultipleChoiceField(
required=False,
...
widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-inline'})
)
On my Django 2.2.6 above solutions did not worked well, so I post my solution after many tries and following the breadcrumbs until the django forms widget templates used.
I had to override 2 templates, and heritage my own widget class and then point it.
The modified default django templates have been:
- django/forms/templates/django/forms/widgets/input_option.html
- django/forms/templates/django/forms/widgets/multiple_input.html
Now they are:
PROJECT_NAME/PROJECT_APP/templates/admin/horizontal_option.html
{% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %} class="radio-inline">{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}
PROJECT_NAME/PROJECT_APP/templates/admin/horizontal_radios.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 %}
{% include option.template_name with widget=option %}{% endfor %}{% if group %}
</ul></li>{% endif %}{% endfor %}
</ul>{% endwith %}
- The first one includes a hardcoded class:
class="radio-inline"
at labels, which in default Django had nothing - The second one the rendering of the set of radios, I removed the extra HTML li tags they were rendered inside the internal ul tag.
Then you need to create your own widget class:
from django.forms import RadioSelect
class HorizontalRadioSelect(RadioSelect):
template_name = 'admin/horizontal_radios.html'
option_template_name = 'admin/horizontal_inputs.html'
And finally, in my case, I pointed to it overriding formfield_overrides
class attribute in my admin. But you can do this in your models too I think:
formfield_overrides = {
models.BooleanField: {'widget': HorizontalRadioSelect(choices=[(True, "Yes"), (False, "No"), (None, "Unknown")],)},
}