在Django管理员中保存时捕获异常?

时间:2021-01-12 00:21:25

I have a pre_save signal handler on a bunch of models, which write to a different database. If something goes wrong, I'd like to abort the whole save, or failing that give a message to the user.

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

Based on Display custom message from signal in the admin, I wrote a mixin with methods like:

基于在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)

This allows me to throw an Exception from the pre_save handler and show the message to the user. The problem is, even though this winds up skipping the actual Model.save(), the admin console doesn't see anything, so it still reports the object as successfully saved.

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

If I changed the pre_save handler to a post_save handler, that would allow the base Model.save() to occur and at least Django would report the correct state of things, but the information I need in the other database is based on the previous state of the object, so I need to get to it before the save.

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

I've also considered stuffing the error message into the object itself in the pre_save and pulling it out in the mixin's save_model() -- but this gets more complicated in the other ModelAdmin save methods like save_formset().

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

Is there any good way to do this?

有没有好办法呢?

1 个解决方案

#1


1  

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.

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

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清洁方法(自我)

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')

#1


1  

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.

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

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清洁方法(自我)

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')