python django postgresql denormalization django-signals

python - Django: Cómo acceder a la instancia original(no modificada) en la señal post_save



postgresql denormalization (1)

Quiero realizar una desnormalización de datos para un mejor rendimiento, y poner una suma de votos que mi publicación de blog recibe dentro del modelo de publicación:

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()

Por supuesto, necesito mantener el valor de Post.rating actual. Normalmente, usaría los activadores de base de datos para eso, pero ahora he decidido hacer una señal post_save (para reducir el tiempo de proceso de la base de datos):

# 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...?

¿Cómo puedo acceder al valor de instancia antes de guardarlo? En los activadores de base de datos, tendría predefinidas OLD y NEW para esto, pero ¿hay algo como esto en las señales de post_save?

ACTUALIZAR

La solución basada en la respuesta de Mark:

# 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()


Creo que post_save es demasiado tarde para recuperar la versión no modificada. Como su nombre lo indica, los datos ya se han escrito en la base de datos en ese momento. Deberías usar pre_save en pre_save lugar. En ese caso, puede recuperar el modelo de la base de datos a través de pk: old = Vote.objects.get(pk=instance.pk) y verificar las diferencias en la instancia actual y en la instancia anterior.