I know who to replace the ManyToMany Widget in the django admin interface:
class SomeModelAdmin(admin.ModelAdmin):
filter_horizontal = ('users',)
But how to replace the default widget in all views?
I guess this could be implemented without changing one line in my code or in django.
It would be great if I could the something like the Author part (two boxes for a ManyToMany input) in this picture with a widget:
I can use ctrl + click, but my users can't. They want an easier way.
Is there a way to replace all select-multiple widgets without many changes in my code?
You can use a base class which ovride formfield_for_manytomany
from django.contrib.admin import widgets
class ManyToManyAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
kwargs['widget']= widgets.FilteredSelectMultiple(
db_field.verbose_name,
db_field.name in self.filter_vertical
)
return super(admin.ModelAdmin, self).formfield_for_manytomany(
db_field, request=request, **kwargs)
class SomeModelAdmin(ManyToManyAdmin):
pass
If I do not understand your question, please clarify in the comments.
The Django Form Widgets Documentation offers several pre-fab widgets that you can use to specify how a field in your form is rendered.
Without modifying the code in my views, I can simply add a widget
keyword arg to the appropriate form fields.
forms.py (v1)
class TestForm(forms.Form):
CHOICES = (
(1, "choice1"),
(2, "choice2"),
(3, "choice3"),
)
field = forms.ChoiceField(choices=CHOICES)
This renders as a dropdown select
:
<select id="id_field" name="field">
<option value="1">choice1</option>
<option value="2">choice2</option>
<option value="3">choice3</option>
</select>
Now adding the widget
keyword arg to my field:
forms.py (v2)
field = forms.ChoiceField(choices=CHOICES, widget=forms.CheckboxSelectMultiple)
This renders as a list of checkboxes:
<ul id="id_field">
<li>
<label for="id_field_0"><input id="id_field_0" name="field" type="checkbox" value="1" /> choice1</label>
</li>
<li>
<label for="id_field_1"><input id="id_field_1" name="field" type="checkbox" value="2" /> choice2</label>
</li>
<li>
<label for="id_field_2"><input id="id_field_2" name="field" type="checkbox" value="3" /> choice3</label>
</li>
</ul>
It is also possible to add widgets that are used by Django Admin. See Django multi-select widget? for more information about this. Simply import the appropriate widget:
from django.contrib.admin.widgets import FilteredSelectMultiple
and use that instead. Note that in this particular case you will also need to include the form's media
to get the desired effect.
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