You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django首页模板获取商品点赞数及多商品点赞问题求助

Django商品点赞功能异常修复方案

问题描述

我尝试在首页模板中显示每个商品的点赞数,页面包含多个商品,但当前代码运行时Django抛出各类异常,无法正常实现功能。

现有代码

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')

index.html

{% 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>

错误点分析

  1. 取消点赞查询错误:Like.objects.get(user=request.user)仅按用户查询会返回多条记录,引发MultipleObjectsReturned异常,需同时指定product过滤条件。
  2. 点赞数统计错误:Like.objects.all().count是引用方法而非调用,需添加();且应统计当前商品的点赞数,而非所有商品的总点赞数。
  3. 模板取值错误:Django模板无get过滤器,直接用like_counts[product.id]会在键不存在时报错,需用安全的取值方式。
  4. 视图异常未处理:views_count中用Product.objects.get()会引发DoesNotExist异常,需改用get_object_or_404。
  5. 查询效率低下:循环每个product统计点赞数会产生N+1次数据库查询,应改用annotate批量统计。

修复后的代码

views.py

from django.db.models import Count

@login_required
def home(request):
    # 用annotate批量统计每个商品的点赞数,提升查询效率
    products = Product.objects.annotate(like_count=Count('like'))
    liked_products = Like.objects.filter(user=request.user, product__in=products).values_list('product_id', flat=True)
    context = {
        "products": products,
        "liked_products": liked_products,
        "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)
    like_obj, created = Like.objects.get_or_create(user=request.user, product=product)
    
    if created:
        # 新增点赞逻辑
        print('product liked')
    else:
        # 取消点赞逻辑
        like_obj.delete()
        print('product like removed')
    
    # 获取当前商品最新点赞数
    current_likes = Like.objects.filter(product=product).count()
    return JsonResponse({"status": "success", "likes": current_likes})

def views_count(request, product_id):
    item = get_object_or_404(Product, id=product_id)
    item.views_count += 1
    item.save()
    return redirect('home')

index.html

{% 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> 
       {{ product.like_count|default:0 }}
   </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>

额外说明

  • 修复后的代码使用annotate将点赞数直接注入Product对象,避免额外的字典存储和重复查询。
  • 用get_or_create简化点赞/取消点赞的逻辑,减少冗余代码。
  • 模板直接调用product.like_count,更直观且避免过滤器错误。

内容的提问来源于stack exchange,提问作者Leroy Mapunzwana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:32:21