django - 在 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()
方法更新其项目的分数。我将整个事情放在原子事务中,因为很明显,我不希望更新评论并且项目的分数保持未更新。这就像潜在错误的滋生地。无论如何,这是正确的方法吗?我觉得我无法在本地服务器上对此进行测试,因为不可能创建一个保存评论但不更新分数的错误。谢谢。
注意:我知道有更好的方法可以根据评论处理项目的分数。这不是问题的重点。为了解释我想要做什么,这是一个虚构的场景。所以,拜托,没有提到这一点的答案。
解决方案
Yes, you could do it as you have mentioned but it is better to use business logic/ transaction logic outside of save() method. This would provide you better integrity and also abstraction.
Writing this logic inside save function is shorthand to do (pretty easy).
other way to do this
utils.py
def update_score(*args, **kwargs):
with transaction.atomic():
review = Review(*args, **kwargs)
review.item.set_score()
review.save()
If this wouldn't helpful for you than writing that transaction block inside save() method or simply pick your code into other method and wrap that with exception but handle that try-catch block with proper exception because it makes side effects / Buggy code. Rest of the things would be fine and work.
Just remember that do not handle exceptions inside the transaction atomic block.
推荐阅读
- ios - 为什么我们不能在 oc 或 swift 中直接捕获 Kotlin 代码产生的异常?
- python - 如何在 django admin 中进行多选功能
- android - 防止谷歌凭据保存在android中
- ruby-on-rails - 无法在 ubuntu 20.04 上安装 bcrypt
- c++ - GCC 生成的代码比 G++ 慢 10 倍
- node.js - 将道具/参数传递给 HOC
- php - 如何删除特定的数据库值
- angular - ionic build error: 运行子进程 ng 时发生错误
- single-sign-on - Keycloak SSO 用户即使在单击注销后也不会注销
- transform - 在 Jolt 中从不同的输入数组和对象准备列表