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.