Django pre_save信号 - 异常会导致事务失败吗?

时间:2014-03-05 20:23:54

标签: python django django-signals

我想在创建用户之前执行一些自定义操作。我想到了使用pre_save信号。如果其中一个动作引发异常,则停止该事务,中止创建用户等。

  1. 这是要走的路吗?如果在这一步中出现故障(这是必需的行为),它会中止保存吗?我怀疑是这样但是找不到关于它的文档。

  2. 获得未来user.id的最佳做法是什么?根据我的理解,它在预存时尚不存在,但我需要它作为一些额外自定义操作的输入。

  3. 由于

2 个答案:

答案 0 :(得分:3)

来自docs

  

在打电话之前,无法确定身份证的价值   save(),因为该值由您的数据库确定,而不是由   Django的。

因此,如果预保存处理需要user.id,我担心这是不可能的。

答案 1 :(得分:3)

以下是两部分答案:

  1. 是的,在pre_save()信号中引发异常将中止对save()方法的调用。例如,我在pre_save()中执行了此操作:

    if SOME_TEST:
        raise exceptions.ParseError(detail="I reject your data. Here is why.")
    

    注意:这是使用DRF例外,但我会假设你知道如何提出你喜欢的任何例外。

  2. 您可以使用post_save()信号在save()方法之后获取id。但如果这对你不起作用,那么下面是我在pre_save()中做你想要的一些策略的原始解释:

  3. 在pre_save中,您可以访问User.objects.all()(当然,如果您导入User模型)。如果您使用的是标准用户模型,则User.id值为AUTO INCREMENT。因此,如果您需要了解新用户的价值,只需获取当前数据库中最高的User.id(即:创建的最后一个用户的ID)。这是一个简单的查询:

    last_user = User.objects.latest('id')

    然后,当然,last_user.id会为您提供上次创建的用户的ID值,如果您添加一个,则您将拥有下一个用户ID。当然,如果您有一个繁忙的网站,您可能会遇到一些同时创建用户的问题。风险是这个值是由两次(或多次)用户创建尝试收到的,其中一个(或多个)最终错误。

    当然,您始终可以将另一个字段设置为primary_key=True,这将替换模型上的id字段。然后你可以设计出任何你想象的索引机制!您可以使用唯一特征的哈希值。例如:User.username具有唯一约束,您可以将其作为数字ID进行哈希或十六进制编码,以预先确定User.id。或者您可以将id字段留在原位并通过为obj.id赋值来在pre_save中手动设置它。它可能是你想要的任何东西。即使是哈希值!