Hahan't
Hahan't

Reputation: 487

Django. How to find out a user liked a post or didn't?

I have 2 models. Product and Favorite (its kind of like)
Favorite has relationship to product and user. I need to check in templates do a user have relationship with a product for inserting like or unlike button.

class Favorite(models.Model):
    """User favorite products"""
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='favorites')
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='favorites')


class Product(models.Model):
    """Store product"""
    ...

In template I have:
{% for product in products %} ...

I'd think i can do it like that {% if product in user.favorites.all %}
But i dont know how to get all favorite products instead of favorites

How i can solve it in templates?

Upvotes: 2

Views: 1017

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

How I can solve it in templates?

Do not solve this in the templates. Templates should implement rendering logic, not business logic. Django's template language deliberately restricts syntax to prevent people from writing complicated logic in the template.

You can annotate the QuerySet with an Exists subquery [Django-doc] to check if the user:

from django.db.models import Exists, OuterRef

Product.objects.annotate(
    is_favorite=Exists(
        Favorite.objects.filter(user=user, product_id=OuterRef('pk'))
    )
)

The Products that arise from this queryset will have an extra attribute .is_favorite that is True if there exists a Favorite for the given user, and False otherwise.

Likely user is request.user.

You might want to make the combination of product and user unique with a UniqueConstraint [Django-doc] to prevent a user adding the same product multiple times to Favorite:

from django.conf import settings

class Favorite(models.Model):
    """User favorite products"""
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='favorites'
    )
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
        related_name='favorites'
    )

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['user', 'product'], name='favorite_once')
        ]

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Upvotes: 9

Related Questions