#Instance field updates on model's save() method, but not on delete() method.

1 messages · Page 1 of 1 (latest)

solemn wave
#

For my Django + HTMX web app, I have the Like model, which belongs to either a blog instance or a comment instance. For the Blog and Comment models, I cache the like count with the like_count field. So anytime a like instance is saved or deleted, like_count is updated again, and I overrode the Like model's save() and delete() methods to handle this logic. However, like_count gets updated on the UI just fine when a new like instance is created, but not when it is deleted, and I have to reload the page for this to happen. What's the problem here? Here is my code:

#
# Comment and Blog models
class Comment(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    blog = models.ForeignKey(
        "blog.Blog", on_delete=models.CASCADE, related_name="comments"
    )
    content = models.TextField()
    liked_by = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through="Like",
        through_fields=("comment", "user"),
        related_name="liked_comments",
        blank=True,
    )
    like_count = models.PositiveIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    objects = CommentManager()

    def __str__(self):
        return self.content

class Blog(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="blogs"
    )
    title = models.CharField(max_length=100)
    description = models.TextField()
    picture = models.ImageField(blank=True)
    saved_by = models.ManyToManyField(
        settings.AUTH_USER_MODEL, related_name="saved_blogs", blank=True
    )
    liked_by = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through="interaction.Like",
        through_fields=("blog", "user"),
        related_name="liked_blogs",
        blank=True,
    )
    like_count = models.PositiveBigIntegerField(default=0)
    comment_count = models.PositiveBigIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = BlogQuerySet.as_manager()

    def __str__(self):
        return self.title
#
# Like model (the save and delete handle the logic)
class Like(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    blog = models.ForeignKey(
        "blog.Blog", null=True, blank=True, on_delete=models.CASCADE
    )
    comment = models.ForeignKey(
        Comment, null=True, blank=True, on_delete=models.CASCADE
    )

    class Meta:
        constraints = [
            CheckConstraint(
                condition=(
                    Q(blog__isnull=False, comment__isnull=True)
                    | Q(blog__isnull=True, comment__isnull=False)
                ),
                name="only_one_instance",
            ),
            *[
                UniqueConstraint(fields=["user", field], name=f"unique_like_{field}")
                for field in ("blog", "comment")
            ],
        ]

    def update_like_count(self):
        instance = self.blog or self.comment
        instance.like_count = instance.liked_by.count()
        instance.save(update_fields=["like_count"])

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        self.update_like_count()

    def delete(self, *args, **kwargs):
        super().delete(*args, **kwargs)
        self.update_like_count()