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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在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处理程序中抛出一个Exception并向用户显示该消息。问题是,即使最终跳过实际的Model.save(),管理控制台也看不到任何内容,因此它仍然会将对象报告为已成功保存。

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

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

有什么好办法吗?

答案

我想出了这个,它混入了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错误重定向。 (注意这将禁用调试堆栈跟踪处理。您可以添加一些条件处理来重新添加)。

另一答案

抓住这种错误不应该是可取的。这可能意味着您向用户展示微妙的信息,例如关于数据库(如果存在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')

以上是关于在Django admin中保存时捕获异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何捕获 Django HTTP 异常?

如何在 Django rest 框架中捕获 Model.DoesNotExist 异常?

在 Django Admin 中保存模型之前显示警报消息

国际化时django.po中的msgstr =“”为中文时,django-admin.py compilemessages 出错:无效的多字节序列

django admin 在保存时重定向到错误的端口

Django Admin,保存时调用函数