在Django中使用原子事务处理模型的save方法

时间:2019-04-06 16:11:39

标签: django

老实说,这个问题很不言而喻。我有2个相关模型。它是这样的:

from django.db import IntegrityError, transaction

class Item(models.Model):
    total_score = models.IntegerField()

    def set_score(self):
         ...

class Review(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    score = models.IntegerField()

    def save(self, *args, **kwargs):
        try:
            with transaction.atomic():
                super(Review, self).save(*args, **kwargs)
                self.item.set_score()
        except IntegrityError:
            handle_exception()

基本上,每当保存评论时,都会使用set_score()方法来更新其项目的分数。我把整个事情放在原子事务中,因为显然,我不想更新评论,而项目的分数保持不变。那就像潜在的错误的温床。无论如何,是正确的方法吗?我觉得我无法在本地服务器上对此进行测试,因为不可能创建会保存评论但不会更新分数的错误。谢谢。

注意:我知道有一种更好的方法可以根据商品的评论来处理商品的得分。这不是问题的重点。为了解释我要做什么,这是一个虚构的方案。因此,请无任何提及。

1 个答案:

答案 0 :(得分:1)

是的,您可以按照前面提到的方法进行操作,但是最好在save()方法之外使用业务逻辑/事务逻辑。这样可以为您提供更好的完整性和抽象性。

在保存功能中编写此逻辑很简单(非常容易)。

另一种方法

utils.py

def update_score(*args, **kwargs):
    with transaction.atomic():
        review = Review(*args, **kwargs)
        review.item.set_score()
        review.save()

如果这比在save()方法中编写该事务块或只将代码插入其他方法并用异常包装,但用适当的异常处理try-catch块对您有帮助,则这会产生副作用/错误的代码。其余的一切都可以正常工作。

  

请记住,不要在事务原子块内部处理异常。