Convert select multiple widget to checkboxes in django admin form

django django-admin django-mptt jquery

I think this should be a nice post talking about the substitution of the default multiple select widget used in django admin interface to deal with m2m fields, with a multiple checkbox widget.

Yes I know, you may solve it this way, but I don't like such solution very much, and I think it is just not perfect for some reasons:

  • At the time of this writing the add related functionality (+) seems to be broken, throws an error, at least for me
  • It just can't be used with the django-mptt application, which is awesome to deal with data which have a tree like structure

So to graphically explain what we want to do here, say we want this:

to become like this:


Imagine a case where the modification form is used by many users which are unfamiliar with the use of the computer. The problem here is that when an user edits the record, if he doesn't keep pressed the ctrl key when adding stuffs will loose all the previous selected ones. Yes I know, it would be enough to recharge the page, but we are talking about unexperienced persons.

Another reason could just be that we prefer checkboxes.

Ok, I'm aware of the existence of the filter_horizontal and filter_vertical options for instances of the ModelAdmin class, but they don't work as expected with django-mptt.

My solution

For the above reasons I've decided to use a custom solution, which essentialy involves only javascript.

If you've already spent some minutes over this blog you know I'm mootools addicted, but here, sigh, I've had to work with jquery, which I really, really don't like, so the code I've written can be surely improved.

The goal of such solution is that the add related functionality is supported, and also the django-mptt m2m fields are supported, like TreeManyToManyField.


There are no requirements.

But, if you want to benefit of the resize functionality (look at the south-west corner of the image above), you have to use jquery-ui and adapt it a bit, we'll see more about it after.

So let's go step by step.

Step one

I've created a gist with all the javascript and css you need to do the trick.

So make the css available in the admin form by adding it to the admin.css or adding a custom css file, and then create a new file in which insert the given javascript.

Now you have to load the javascript in the form page, so you can define it in the Media class of the ModelAdmin instance:

class myModelAdmin(admin.ModelAdmin):
  class Media:
    js = ['admin/js/mselect-to-mcheckbox.js']
    css = {
      'all': ('admin/css/mselect-to-mcheckbox.css')

Ok, now look at the last part of the javascript, line 80, all you have to do is to change the selector passed to the function mselectTOmcheckbox in order to decide which fields to convert, and the game is done.

Step two

Actually there is not a required step two, but you may want to add the resize functionality to your new widget, so you have to:

  • Download a jquery-ui custom release with support to the resizable functionality (including a js, a css and some images)
  • Change the js a bit (the argument passed to all the single execution functions must be django.jQuery and not jQuery!). See below to download the adjusted files.
  • Adjust the downloaded css images paths in order to fit your folder structure
  • Add the jquery-ui js and css to Media class of the ModelAdmin instance
class myModelAdmin(admin.ModelAdmin):
  class Media:
    js = ['admin/js/jquery-ui-1.10.2.custom.js', 'admin/js/mselect-to-mcheckbox.js']
    css = {
      'all': ('admin/css/jquery-ui-1.10.2.custom.css', 'admin/css/mselect-to-mcheckbox.css',)

And now you're OK!
The widget should work as expected, the + link used to add related object should also work as expected, the widget should do the trick also with the django-mptt m2m fields, and the multiple checkbox container should be resizable.

All the work to do is quite well explained IMO, but here you may download a package with all the resources, especially the jquery-ui library modified to work in the django admin. Notice that in such package I've changed the css images path of the jquery-ui css to fit my folder structure which was:


And here you may download all the resources we talk about.

Enjoy it and comment here for problems or suggestions.

Subscribe to abidibo.net!

If you want to stay up to date with new contents published on this blog, then just enter your email address, and you will receive blog updates! You can set you preferences and decide to receive emails only when articles are posted regarding a precise topic.

I promise, you'll never receive spam or advertising of any kind from this subscription, just content updates.

Subscribe to this blog

Comments are welcome!

blog comments powered by Disqus

Your Smartwatch Loves Tasker!

Your Smartwatch Loves Tasker!

Now available for purchase!