I have been searching for an answer for hours, however every answer I found does not work. Also trying to find a bug on my own didn't bring me any results.
I have created a receiver function
which should update model's total_likes
attribute(based on number of users_like
attribute) every time user click on the like button of the specific image. (This is a part of 'Django by Example` book). But the field's value stays always the same and is equal to default value of 0. Even if I try to assign the value to the field manually, in the django's shell, it does not change(code example in 'Update' section).
Can someone please have a look at the code and point me in the right directions if I am doing something wrong?
I am using Django 1.9.
# models.py
class Image(models.Model):
...
users_like = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='images_liked',
blank=True)
total_likes = models.PositiveIntegerField(default=5)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Image, self).save(*args, **kwargs)
# signals.py
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
from .models import Image
@receiver(m2m_changed, sender=Image.users_like.through)
def users_like_changed(sender, instance, **kwargs):
instance.total_likes = instance.users_like.count()
instance.save()
# apps.py
from django.apps import AppConfig
class ImagesConfig(AppConfig):
name = 'images'
verbose_name = 'Image bookmarks'
def ready(self):
# import signal handlers
import images.signals
# __init__.py
default_app_config = 'images.apps.ImagesConfig'
When I run code below from django shell, this does change the total_likes
value, but it looks like it do just temporary:
from images.models import Image
for image in Image.objects.all():
print(image.total_likes)
image.total_likes = image.users_like.count()
print(image.total_likes)
image.save()
print(image.total_likes)
Output from code above:
0 #initial/default value of 0
3 #current number of users who like the picture
3
Because when I run the for loop code again, to see the results(or even check the field value in admin interface) i still get the initial/default value of 0.
Can someone see the problem why the field does not get updated?
Ok, so the problem was with the custom save()
method on the model class.
I needed to call the save()
method of the parent class like this:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Image, self).save(*args, **kwargs)
and it made it work.