在Django中,如何在Model.save()期间引发非验证错误?

时间:2014-10-28 21:20:19

标签: python django

我正面临一个奇怪的用例,我不知道如何继续。

我正在覆盖save()上的DNSRecord Model方法。覆盖的主要原因是为作为保存的一部分必须在外部系统上完成的额外工作添加额外的副作用。其他操作包括:

  1. 从IPAddress模型表中构建一个空的IPAddress实例,

  2. 更新所述IPAddress,

  3. 进行一系列REST API调用以在UltraDNS中实际创建DNS记录。

  4. 除了写入DNSRecord之外,这三个副作用中的每一个都可能最终失败,此时应该中止保存(原子性)并报告给用户。

    我的交易安全性有所下降,但我不确定如何以有意义的方式将错误报告给用户。我已经读过ValidationErrors不适合在这里使用,有些消息来源说,raise根本不save()任何例外,这似乎太严格了。我应该如何处理这些案例,这两种情况都允许我提供反馈,说明错误发生的原因,同时仍然优雅地失败?

    作为抬头,我只使用管理界面。

1 个答案:

答案 0 :(得分:1)

我通常将此检查保留在原子块内,然后引发异常,看看是否可以从中获取任何内容 -

在模型中 -

def save(self, *args, **kwargs):
    if self.pk is None:
        ....

    if self.date_created is None:
        .....

    with transaction.atomic():
        self.clean()  # my personal clean method
        raise Exception("This is a dummy exception") #this will automatically roll back all the save methods call hierarchy if they are also following this process, to nothing is saved
        super().save()

在视图类(基于类的视图)中向用户显示错误消息 -

def post(self, request, *args, **kwargs):

    if form.is_valid():
        .......  # create the model
        try:
             model.save()
             return self.form_valid(form)
        except Exception as err:
             messages.error(request, str(err))
    return self.form_invalid(form)

然后在模板中将它们显示为 -

<div class="flash_message hide">
                        {% if messages %}
                        <ul class="messages">
                            {% for message in messages %}
                            <li{% if message.tags %} class="alert alert-{{ message.tags }}"{% endif %}>
                            {{ message|safe }}
                            </li>
                            {% endfor %}
                        </ul>
                        {% endif %}
                    </div>

注意:我使用Django Message Framework将消息从视图传递到模板。我也使用twitter bootstrap 3,所以我的模板格式是这样的。

您还可以将Exception子类化以添加自定义错误。