如何为Crispy Forms渲染的CheckboxSelectMultiple选项添加类
Here's a straightforward way to add Bootstrap's col-3 class to each checkbox option while keeping your existing Crispy Forms workflow intact:
1. Create a Custom Checkbox Widget
First, define a custom widget that extends Django's CheckboxSelectMultiple and injects the Bootstrap class into each option's wrapper div. Add this to your forms.py file:
from django.forms.widgets import CheckboxSelectMultiple class BootstrapCheckboxSelectMultiple(CheckboxSelectMultiple): def create_option(self, name, value, label, selected, index, subindex=None, attrs=None): # Get the default option configuration from the parent class option = super().create_option(name, value, label, selected, index, subindex, attrs) # Add the Bootstrap col-3 class to the wrapper div of each option wrapper_attrs = option.get('wrapper_attrs', {}) wrapper_attrs['class'] = f"{wrapper_attrs.get('class', '')} col-3".strip() option['wrapper_attrs'] = wrapper_attrs return option
Note: This uses Django's wrapper_attrs feature, which was added in Django 3.2. If you're on an older version, skip to the alternative template override method below.
2. Update Your Form Field to Use the Custom Widget
Replace the default widget in your topics field with the new custom one:
TOPICS = ( ('ANI', 'Animals'), ('ART', 'Art'), ('COM', 'Communication'), ('CRI', 'Crime'), ('CUL', 'Culture/Society'), ) class YourFormName(forms.Form): # Replace with your actual form class name topics = forms.MultipleChoiceField( choices=TOPICS, required=False, widget=BootstrapCheckboxSelectMultiple() ) # ... your other form fields ...
3. Verify Your Crispy Forms Helper Setup
Ensure your form helper is configured to use Bootstrap (this is likely already in place if you're using Crispy with Bootstrap). For reference, here's a sample helper configuration:
from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Fieldset, Submit class YourFormName(forms.Form): # ... fields ... def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_method = 'post' self.helper.layout = Layout( Fieldset( 'Select Topics', 'topics', # Now renders with col-3 classes on each checkbox option # ... other fields ... ), Submit('submit', 'Submit', css_class='btn-primary') )
How It Works
The create_option method generates the configuration for each individual checkbox option. By adding col-3 to wrapper_attrs, we apply the class directly to the div that wraps each checkbox and its label. This will arrange your options into a clean 4-column grid (since Bootstrap's grid uses 12 columns, 12/3 = 4).
Alternative: Template Override (For Older Django Versions)
If you're using Django <3.2, you can override Crispy Forms' checkbox template to add the col-3 class:
- Create a
crispy_forms/bootstrap4/layoutdirectory in your app's templates folder (adjustbootstrap4to your Bootstrap version). - Create a file named
checkboxselectmultiple.htmlin that directory. - Copy the default template content and modify the option wrapper to include
col-3:{% for choice in field.field.choices %} <div class="form-check col-3"> <input type="checkbox" class="form-check-input" id="id_{{ field.name }}_{{ forloop.counter }}" name="{{ field.name }}" value="{{ choice.0 }}" {% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|stringformat:"s" %}checked{% endif %}> <label class="form-check-label" for="id_{{ field.name }}_{{ forloop.counter }}">{{ choice.1 }}</label> </div> {% endfor %}
内容的提问来源于stack exchange,提问作者horse

