在Django admin中保存时捕获异常?

时间:2014-10-24 18:28:50

标签: django django-admin

我在一堆模型上有一个pre_save信号处理程序,它写入不同的数据库。如果出现问题,我想中止整个保存,或者没有向用户发送消息。

基于Display custom message from signal in the admin,我用以下方法编写了一个mixin:

class SafeSaveMixin(object):
    def save_model(self, request, *args, **kwargs):
        try:
            return super(SafeSaveMixin, self).save_model(request, *args, **kwargs)
        except Exception as e:
            self.message_user(request, e, messages.ERROR)

这允许我从pre_save处理程序中抛出异常并向用户显示消息。问题是,即使最终跳过实际的Model.save(),管理控制台也看不到任何内容,因此它仍然会将对象报告为已成功保存。

如果我将pre_save处理程序更改为post_save处理程序,那将允许基本Model.save()发生,并且至少Django会报告正确的状态,但是信息我另一个数据库中的需求是基于对象的之前的状态,所以我需要在保存之前找到它。

我还考虑将错误消息填充到pre_save中的对象本身并将其从mixin的save_model()中拉出来 - 但这在另一个ModelAdmin中变得更加复杂保存save_formset()等方法。

有没有好办法呢?

2 个答案:

答案 0 :(得分:4)

我想出了这个,它混入了ModelAdmin类中:

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):
        try:
            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)

这不会干扰实际的模型保存过程,只会阻止500错误重定向。 (请注意,这将禁用调试堆栈跟踪处理。您可以添加一些条件处理以将其重新添加。)

答案 1 :(得分:1)

抓住这种错误不应该是可取的。这可能意味着您向用户展示微妙的信息,例如关于数据库(如果存在IntegrityError)。由于这绕过了正常的错误处理,您可能还会错过通知您错误的消息。

如果用户输入了错误/不完整数据需要进行一些检查,那么可以采用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')