Django:如何访问 post_save 信号中的原始(未修改)实例
我想要进行数据非规范化以获得更好的性能,并将我的博客文章收到的投票总数放入 Post 模型中:
class Post(models.Model):
""" Blog entry """
author = models.ForeignKey(User)
title = models.CharField(max_length=255)
text = models.TextField()
rating = models.IntegerField(default=0) # here is the sum of votes!
class Vote(models.Model):
""" Vote for blog entry """
post = models.ForeignKey(Post)
voter = models.ForeignKey(User)
value = models.IntegerField()
当然,我需要保持 Post. rating
值实际。通常我会使用数据库触发器,但现在我决定创建一个 post_save
信号(以减少数据库处理时间):
# vote was saved
@receiver(post_save, sender=Vote)
def update_post_votes(sender, instance, created, **kwargs):
""" Update post rating """
if created:
instance.post.rating += instance.value
instance.post.save()
else:
# if vote was updated, we need to remove the old vote value and add the new one
# but how...?
如何在保存实例值之前访问它?在数据库触发器中,我会为此预定义 OLD
和 NEW
,但是 post_save 信号中有类似的东西吗?
更新
基于马克答案的解决方案:
# vote was saved
@receiver(pre_save, sender=Vote)
def update_post_votes_on_save(sender, instance, **kwargs):
""" Update post rating """
# if vote is being updated, then we must remove previous value first
if instance.id:
old_vote = Vote.objects.get(pk=instance.id)
instance.post.rating -= old_vote.value
# now adding the new vote
instance.post.rating += instance.value
instance.post.save()
I want to do a data denormalization for better performance, and put a sum of votes my blog post receives inside Post model:
class Post(models.Model):
""" Blog entry """
author = models.ForeignKey(User)
title = models.CharField(max_length=255)
text = models.TextField()
rating = models.IntegerField(default=0) # here is the sum of votes!
class Vote(models.Model):
""" Vote for blog entry """
post = models.ForeignKey(Post)
voter = models.ForeignKey(User)
value = models.IntegerField()
Ofcourse, I need to keep Post.rating
value actual. Nornally I would use database triggers for that, but now I've decided to make a post_save
signal (to reduce database process time):
# vote was saved
@receiver(post_save, sender=Vote)
def update_post_votes(sender, instance, created, **kwargs):
""" Update post rating """
if created:
instance.post.rating += instance.value
instance.post.save()
else:
# if vote was updated, we need to remove the old vote value and add the new one
# but how...?
How can I access the instance value before it was saved? In database triggers, i would have OLD
and NEW
predefines for this, but is there something like this in post_save signals?
UPDATE
The solution based on Mark's the answer:
# vote was saved
@receiver(pre_save, sender=Vote)
def update_post_votes_on_save(sender, instance, **kwargs):
""" Update post rating """
# if vote is being updated, then we must remove previous value first
if instance.id:
old_vote = Vote.objects.get(pk=instance.id)
instance.post.rating -= old_vote.value
# now adding the new vote
instance.post.rating += instance.value
instance.post.save()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我相信
post_save
已经来不及检索未修改的版本了。顾名思义,此时数据已经写入数据库。您应该使用pre_save
来代替。在这种情况下,您可以通过 pk 从数据库检索模型:old = Vote.objects.get(pk=instance.pk)
并检查当前实例和前一个实例之间的差异。I believe
post_save
is too late to retrieve the unmodified version. As the name implies the data has already been written to the db at that point. You should usepre_save
instead. In that case you can retrieve the model from the db via pk:old = Vote.objects.get(pk=instance.pk)
and check for differences in the current instance and the previous instance.这不是一个最佳解决方案,但它确实有效。
This is not an optimal solution, but it works.
您可以使用 django-model-utils 中的 FieldTracker: https://django-model-utils.readthedocs.io/en/latest/utilities.html#field-tracker
You can use the FieldTracker from django-model-utils: https://django-model-utils.readthedocs.io/en/latest/utilities.html#field-tracker