Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show database errors to user in Django Admin

Background: my Django application sits onto top of a pre-existing Postgresql database. This database has a very complex network of triggers and constraints.

Question: In the Django Admin, if a user causes a DatabaseError on save, I would like to show the error back to them in a user friendly format, similar to the builtin forms.ValidationError.

Example (this doesn't work, it causes a 500)

def save_model(self, request, obj, form, change):
    try:
        obj.save()
    except DatabaseError as e:
        raise forms.ValidationError(e)

Expected Result:

Shown to user in Admin, "Database Error: ID 58574 - Price is outside customers requested range. Cannot add or update a child row: a foreign key constraint fails."

like image 392
keithhackbarth Avatar asked Nov 15 '13 19:11

keithhackbarth


1 Answers

@twil -- Thanks for your help. You put me on the right track. Really appreciate your help. However, the solution didn't work out of box. Didn't actually show errors in my test case or work with change_view. Here's want I ended up working with.

from django.contrib.admin import ModelAdmin
from django.db import DatabaseError, IntegrityError
from django.contrib import messages


class ShowValidationAdmin(ModelAdmin):

    def add_view(self, request, form_url='', extra_context=None):
        try:
            return super(ShowValidationAdmin, self).add_view(request, form_url, extra_context)
        except (IntegrityError, DatabaseError) as e:

            request.method = 'GET'
            messages.error(request, e.message)
            return super(ShowValidationAdmin, self).add_view(request, form_url, extra_context)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        try:
            return super(ShowValidationAdmin, self).change_view(request, object_id, form_url, extra_context)
        except (IntegrityError, DatabaseError) as e:

            request.method = 'GET'
            messages.error(request, e.message)
            return super(ShowValidationAdmin, self).change_view(request, object_id, form_url, extra_context)

Note: That this version also seems to work cross version (django 1.3 - 1.6). Let me know if anyone has a better approach. I'll wait to award bounty.

like image 141
keithhackbarth Avatar answered Oct 06 '22 09:10

keithhackbarth