The django-bootstrap3 package is used to show django forms with bootstrap.
Most of the fields have their own bootstrap widgets except for:
WIDGETS_NO_REQUIRED = (
AdminFileWidget,
HiddenInput,
FileInput,
CheckboxInput,
CheckboxSelectMultiple
)
Unfortunately that makes the CheckboxSelectMultiple
render as a single line of vertical checkboxes. Not making use of space that well. So how do we change the way it is rendered?
Since django 1.11
, custom renderers simply by changing the template as opposed to overriding the render
method prior to django 1.11
.
So let us figure out which template we need to change. Search the django
source code for CheckboxSelectMultiple
. We find it in django.forms.widgets.CheckboxSelectMultiple
and the template it is using is template_name = 'django/forms/widgets/checkbox_select.html'
.
So we override it:
class ColumnCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
template_name = 'forms/widgets/bootstrap_checkbox_select.html'
Then we create the template in:/templates/forms/widgets/bootstrap_checkbox_select.html
Unfortunately we get an error saying the TemplateDoesNotExist at /xxx/
Now the problem is it is not looking in project DIRs
. This is sorted by adding the following in your settings file:
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
django.forms
to INSTALLED_APPS
Making the Template
So we have copied the contents of django/forms/templates/django/forms/widgets/multiple_input.html
to templates/forms/widgets/bootstrap_checkbox_select.html
Whoops
django-bootstrap is actually rendering the widget or overriding how it is being rendered.
So what we just did makes no difference and even better than that, this is something that can be solved with css. We want to split these checkboxes into columns.
In essence all we need is the following form field:
user = forms.ModelChoiceField(
queryset=get_user_model().objects.all(),
widget=forms.CheckboxSelectMultiple(
attrs={
"checked": "",
"class": "column-checkbox"
}
),
required=False,
empty_label=None
)
and the following css:
.column-checkbox {
padding-top: 20px;
}
.column-checkbox .checkbox {
display: block;
float: left;
width: 25%;
}
There was an issue with the above that made the continer div not have a height. To fix this make sure that overflow: auto;
for the containing div.