django get all the likes made for a post

63 Views Asked by At

i am trying to get all the likes for a specific in the home templates and also they are many products in the template.

this is my views.py

@login_required
def home(request):
    products = Product.objects.all()
    like_counts = {product.id: Like.objects.filter(product=product).count() for product in products}
    liked_products = Like.objects.filter(user=request.user, product__in=products).values_list('product', flat=True)
    context = {
        "products": products,
        "liked_products": liked_products,
        "like_counts": like_counts,
        "categories": Category.objects.all(),
    }    
    return render(request, 'shop/index.html', context)

@login_required
def likeProduct(request, product_id):
    product = get_object_or_404(Product, id=product_id)

    # Check if the user has already liked the product
    if not Like.objects.filter(user=request.user, product=product).exists():
        # Create a new Like object
        Like.objects.create(user=request.user, product=product)
        print('product liked')
        likes = Like.objects.all().count

        return JsonResponse({"status": "success","likes":f'{likes}'})
    else:
        liked = Like.objects.get(user=request.user)
        liked.delete()
        print('product like removed')
        likes = Like.objects.all().count
    return JsonResponse({"status": "success","likes":f'{likes}'})

def views_count(request,product_id):`
    item = Product.objects.get(id=product_id)
    item.views_count += 1
    item.save()

    return redirect('home')

this is my index.html and i am got stuck here now the django is giving all sorts of weird errors and do not know how to solve it:

{% csrf_token %}
<div class="d-flex justify-content-between">
   <button onclick="likeProduct({{ product.id }})" class="btn shadow-none bg-transparent rounded-pill"> <i class="{% if product.id in liked_products %}fas{% else %}far{% endif %} fa-heart"></i> {{ like_counts|default:"0"|get:product.id }}
   </button> 
   <button class="btn shadow-none bg-transparent rounded-pill"><i class="fas fa-star"></i></button> 
   <button class="btn btn-outline-primary"><i class="fas fa-comment"></i></button>
</div>
2

There are 2 best solutions below

1
Pycm On

Change your code as below.

  1. in views.py
@login_required
def home(request):
    context = {
        "products": Product.objects.all(),
        "categories": Category.objects.all(),
    }    
    return render(request, 'shop/index.html', context)
  1. in models.py
class Product(models.Model):

# Youe other fields



# add these lines
#////////////////
    @property   
    def product_like_count(self):
        count = Like.objects.filter(product=self).count()
        return count
#//////////////

  1. in templates
{% for product in products %}


<!-- get id -->
{{ product.id }}


<!-- get like count of current product -->
{{ product.product_like_count }}
<!-- you can access all the fields of a product -->



{% for like in product.like_set.all %}


<!-- get id of like -->
{{ like.id }}
<!--you can access all the fields of a like -->


{% endfor %}




{% endfor %}

0
Leroy Mapunzwana On

like_counts is a context variable passed to the template, containing a dictionary of product IDs and their associated like counts | get:product.id applies the get filter to like_counts.

1.product_list.html

       <div class="d-flex justify-content-between py-0 my-0">
            <button onclick="likeProduct({{ product.id }})"
                    class="btn shadow-none bg-transparent rounded-pill">
                <i class="{% if product.id in liked_products %}fas{% else %}far{% endif %} fa-heart"></i>
                 {{ like_counts| get:product.id}}
            </button>
            <button class="btn shadow-none bg-transparent rounded-pill"><i class="fas fa-star"></i></button>
            <button class="btn btn-outline-primary"><i class="fas fa-comment"></i></button>
        </div>
  1. template_filters.py
from django.template.defaulttags import register

@register.filter
def get(value, arg):
    return value.get(arg, 0)  # Or any default value you prefer```