Django: How to access original (unmodified) instance in post_save signal

2024/11/20 20:24:26

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.valueinstance.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 firstif instance.id:old_vote = Vote.objects.get(pk=instance.id)instance.post.rating -= old_vote.value# now adding the new voteinstance.post.rating += instance.valueinstance.post.save()
Answer

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 use pre_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.

https://en.xdnf.cn/q/26284.html

Related Q&A

timeit and its default_timer completely disagree

I benchmarked these two functions (they unzip pairs back into source lists, came from here): n = 10**7 a = list(range(n)) b = list(range(n)) pairs = list(zip(a, b))def f1(a, b, pairs):a[:], b[:] = zip(…

How to pickle and unpickle to portable string in Python 3

I need to pickle a Python3 object to a string which I want to unpickle from an environmental variable in a Travis CI build. The problem is that I cant seem to find a way to pickle to a portable string …

Using RabbitMQ is there a way to look at the queue contents without a dequeue operation?

As a way to learn RabbitMQ and python Im working on a project that allows me to distribute h264 encodes between a number of computers. The basics are done, I have a daemon that runs on Linux or Mac th…

Pip default behavior conflicts with virtualenv?

I was following this tutorial When I got to virtualenv flask command, I received this error message: Can not perform a --user install. User site-packages are not visible in this virtualenv.This makes s…

How to update user password in Django Rest Framework?

I want to ask that following code provides updating password but I want to update password after current password confirmation process. So what should I add for it? Thank you.class UserPasswordSeriali…

ImportError: No module named xlrd

I am currently using PyCharm with Python version 3.4.3 for this particular project.This PyCharm previously had Python2.7, and I upgraded to 3.4.3.I am trying to fetch data from an Excel file using Pand…

How do I automatically fix lint issues reported by pylint?

Just like we have "eslint --fix" to automatically fix lint problems in Javascript code, do we have something for pylint too for Python code?

Conversion from JavaScript to Python code? [closed]

Closed. This question is seeking recommendations for books, tools, software libraries, and more. It does not meet Stack Overflow guidelines. It is not currently accepting answers.We don’t allow questi…

connect to a DB using psycopg2 without password

I have a postgres database on my localhost I can access without a password$ psql -d mwt psql (8.4.12) Type "help" for help.mwt=# SELECT * from vatid;id | requester_vatid |...-----+---------…

Shebang doesnt work with python3

I have the following program:#!/usr/local/bin/python3print("Hello")Via terminal I do test.py and I get:Traceback (most recent call last):File "/usr/lib/python3.3/site.py", line 629,…