Reputation: 3789
I have a form that offers options for signing up to mailing lists.
field = forms.ModelMultipleChoiceField(
queryset=MailingList.objects.filter(
list_active=True),
widget=forms.CheckboxSelectMultiple(
{'class': 'no-bullet-list',
'style': 'list-style: none;'}))
# Specifying class and style both is excessive, I'm still exploring.
Meanwhile, I've put this in my CSS sheet:
.no-bullet-list {
list-style-type: none;
}
This does what I want, rendering a correct set of choices as checkboxes, but it also puts bullets before them. This is because the rendered HTML looks like this:
<ul id="id_newsletters" class="no-bullet-list">
<li><label for="id_newsletters_0">
<input type="checkbox" name="newsletters" value="1"
class="no-bullet-list" style="list-style: none;"
id="id_newsletters_0">
Annonces</label>
</li>
That snippet comes from django/forms/templates/django/forms/widgets/multiple_input.html
, which is the result of the definition of CheckboxSelectMultiple
in django/forms/widgets.py
.
class CheckboxSelectMultiple(ChoiceWidget):
allow_multiple_selected = True
input_type = 'checkbox'
template_name = 'django/forms/widgets/checkbox_select.html'
option_template_name = 'django/forms/widgets/checkbox_option.html'
def use_required_attribute(self, initial):
# Don't use the 'required' attribute because browser validation would
# require all checkboxes to be checked instead of at least one.
return False
def value_omitted_from_data(self, data, files, name):
# HTML checkboxes don't appear in POST data if not checked, so it's
# never known if the value is actually omitted.
return False
def id_for_label(self, id_, index=None):
""""
Don't include for="field_0" in <label> because clicking such a label
would toggle the first checkbox.
"""
if index is None:
return ''
return super().id_for_label(id_, index)
My attempt to add CSS attributes to the <li>
only succeeded in adding to the <ul>
and to the <input ...>
, so it doesn't do what I want (remove the bullets). In addition, it appears there's no customisation hook to style the <li>
.
The only way I see to do this is to copy the full widget definition and its template to my app and modify them. This is icky. Is there a portable way to style the checkbox list items?
FWIW, my own template does this:
<form method="post">{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
{% for field in form %}
<p>
{{ field.label }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
</p>
{% for error in field.error_messages %}
<p style="color: red">{{ error }}</p>
{% endfor %}
{% endfor %}
<button type="submit" class="btn btn-outline-primary">Je m'inscris</button>
</form>
Upvotes: 0
Views: 625
Reputation: 3258
Your forms.py should work. A couple steps to take to debug:
clear your browser history. I remember I was extremely frustrated with css, and it turns out that they were caching problems.
If step 1) not working, open your chrome develop tools, and see if your css is loading. If you get something like below:
GET http://127.0.0.1:8000/static/soforms/css/soforms.css
net:: ERR_ABORTED 404 (Not Found)
.
2-1) then try to make sure you have
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR.joinpath('static_files')
2-2) see if your css
file is located in the right place.
2-3) in a rare case, it might be due to you forgot migrate
after you generate your app
. This actually happened to me today.
Upvotes: 1