Django Admin Confirmation Dialog

Posted by Mark Oosterveld on November 01, 2021 · 1 mins read

One of my initial tasks, when I first joined Perpetua, was to add a boolean field to a table managed by Django. Setting this field would be done via the Django admin interface, and would have major implications to how another part of the system behaved, so we wanted to caution the user, and make sure they understood these implications.

The ideal approach would be to prompt the user when setting the field, giving them a chance to confirm or cancel the selection.

I was familiar with Django, but had never actually worked with it before, so the first thing I did was go through the tutorial.

I quickly discovered that by adding help_text to model of the new field, I could display the warning in the admin interface. But this was just a static display, and didn’t actually make the user confirm anything.

I continued through the tutorial, but didn’t find what I was looking for. So, it was time to hit Google!

Google django admin confirmation dialog

Lots of posts on building custom forms. Resigned to this fate, I opened up the Working with forms documentation, and started reading.

Eventually, I stumbled on the documentation for Form Assets and the Media class. Using this, I was able to inject some Javascript into the form.

class AccountCreationForm(forms.ModelForm):
    ...
    class Media:
        js = ("/static/service/admin/account.js")

Now, all I needed to do was add a change listener on the checkbox, and show a confirmation dialog when the checkbox was clicked. Fortunately, Django ships with jQuery! Adding it to the page was as easy as updating the Media class:

    class Media:
        js = ("admin/js/jquery.init.js", "/static/service/admin/account.js")

The last step is to hook into the change event on the checkbox. Again, Django has our back here, and automatically adds an id field for us.

This is what the final Javascript code looked like:

(function($) {
    $(document).ready(function() {
        const checkbox = $('#id_boolean_field');

        checkbox.change(({ currentTarget: { checked } }) => {
            if (checked) {
                const approve = confirm(`
                    WARNING:

                    Checking this box will have the following implications:
                       ...

                    Make sure that this is what you want.
                `);

                if (approve === false) {
                    checkbox.prop('checked', false);
                }
            }
        });
    });
})(django.jQuery);

And with that, it’s done! What initially looked like a difficult task, creating a bunch of custom views, actually turned out to be quite easy. All it took was a little digging into the documentation.