[Fixed]-Catch exception on save in Django admin?


I’ve come up with this, which gets mixed in to the ModelAdmin class:

class InternalModelAdminMixin:
    """Mixin to catch all errors in the Django Admin and map them to user-visible errors."""
    def change_view(self, request, object_id, form_url='', extra_context=None):
            return super().change_view(request, object_id, form_url, extra_context)
        except Exception as e:
            self.message_user(request, 'Error changing model: %s' % e.msg, level=logging.ERROR)
            # This logic was cribbed from the `change_view()` handling here:
            # django/contrib/admin/options.py:response_post_save_add()
            # There might be a simpler way to do this, but it seems to do the job.
            return HttpResponseRedirect(request.path)

This doesn’t interfere with the actual model save process, and simply prevents the 500 error redirect. (Note this will disable the debug stacktrace handling. You could add some conditional handling to add that back in).


Catching this kind of errors should not be desirable. This could mean you expose delicate information to your users, e.g. about database (if there is an IntegrityError). As this bypasses the normal error handling, you might also miss messages that inform you about errors.

If there’s some check required for wrong/incomplete data a user has entered, then the way to go is to do this in def clean(self)

def clean(self):
    cleaned_data = super(ContactForm, self).clean()
    field_value = cleaned_data.get('field_name')
    if not field_value:
        raise ValidationError('No value for field_name')


class YourModel(models.Model):
    def clean(self):
        # do some validation
        # or raise ValidationError(...)

    def save(self, *args, **kwargs):
        super(YourModel, self).save(*args, **kwargs)

It usually works, and you should not do any validation in other place.

But if you use RelatedField with InlineAdmin, and validation by related instance.
Sometimes it will be wrong, Django won’t render your Exceptions.

Like this question: how to display models.full_clean() ValidationError in django admin?

It confuse me about two month. And make me saw lots sources code.

Just now,I fixed it in my project(maybe…)

Hope no bug…



We need to override changeform_view of your admin

In your app/admin.py

from .model import SomeModel # => import your model from where it exists (.model might not be valid for you)
from django.contrib import admin, messages
from django.http import HttpResponseRedirect

class SomeModelAdmin(admin.ModelAdmin):

    def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
            return super(SomeModelAdmin, self).changeform_view(request, object_id, form_url, extra_context)
        except Exception as e:
            self.message_user(request, e, level=messages.ERROR)
            return HttpResponseRedirect(request.path)

admin.site.register(SomeModel, SomeModelAdmin)

Leave a comment