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

Django实现点击心形按钮添加/移除商品至心愿单功能问题

心愿单功能问题排查与修复方案

一、路由配置检查

  1. 先确认urls.py中是否正确注册视图函数路由,且重定向名称保持统一:
    • 视图add_to_favorie重定向目标是redirect('detail', id=id),而remove_from_favorie是redirect('product_detail', id=id),两处名称不统一,需修改为一致(比如统一用product_detail)。
    • 示例路由配置:
      path('favorite/add/<int:id>/', views.add_to_favorie, name='add_to_favorite'),
      path('favorite/remove/<int:id>/', views.remove_from_favorie, name='remove_from_favorite'),
      path('product/detail/<int:id>/', views.product_detail, name='product_detail'), # 确保该路由名称与重定向目标一致
      

二、视图函数逻辑修正

  1. add_to_favorie已实现添加/移除的切换逻辑(通过get_or_create判断,存在则删除),remove_from_favorie属于冗余函数,前端可统一调用add_to_favorie实现toggle功能。同时修正重定向名称:
    @login_required(login_url='login')
    def add_to_favorie(request,id):
        product = get_object_or_404(Product, id=id)
        favorie, created = Favorie.objects.get_or_create(user=request.user, product=product)
        if not created:
            favorie.delete()
        return redirect('product_detail', id=id) # 改为统一的重定向名称
    
  2. 给remove_from_favorie也加上@login_required装饰器,避免未登录用户访问报错:
    @login_required(login_url='login')
    def remove_from_favorie(request, id):
        product = get_object_or_404(Product, id=id)
        favorite = Favorie.objects.filter(user=request.user, product=product).first()
        if favorite:
            favorite.delete()
        return redirect('product_detail', id=id)
    

三、模板层交互与状态渲染修复

当前模板缺少动态判断商品是否在心愿单和绑定点击事件两个核心部分,修改后代码如下:

<div class="produit p-4 d-flex flex-lg-row flex-column rounded-5 align-items-center justify-content-center">
  <span class="heart-box" data-product-id="{{ product.id }}">
    <!-- 根据商品是否在用户心愿单,动态渲染对应图标 -->
    {% if product in user.favorie_set.all %}
      <img src="{% static 'produit/images/heart-active.jpg' %}" class="heart-icon" alt="已加入心愿单">
    {% else %}
      <img src="{% static 'produit/images/heart.jpg' %}" class="heart-icon" alt="加入心愿单">
    {% endif %}
  </span>
</div>

<!-- 绑定点击事件,调用后端接口实现切换 -->
<script>
  document.querySelectorAll('.heart-box').forEach(box => {
    box.addEventListener('click', function() {
      const productId = this.dataset.productId;
      // 发送POST请求(需携带CSRF令牌,Django默认拦截无令牌的POST请求)
      fetch(`/favorite/add/${productId}/`, {
        method: 'POST',
        headers: {
          'X-CSRFToken': '{{ csrf_token }}'
        }
      }).then(() => {
        // 局部更新图标,避免整页刷新
        const img = this.querySelector('.heart-icon');
        const isActive = img.src.includes('heart-active');
        if (isActive) {
          img.src = "{% static 'produit/images/heart.jpg' %}";
          img.alt = "加入心愿单";
        } else {
          img.src = "{% static 'produit/images/heart-active.jpg' %}";
          img.alt = "已加入心愿单";
        }
      });
    });
  });
</script>

模板修正说明:

  1. 状态判断:通过{% if product in user.favorie_set.all %}判断商品是否在用户心愿单,动态显示对应图标。
  2. 点击交互:给心形容器绑定点击事件,调用add_to_favorie接口实现切换,局部更新图标提升体验。
  3. CSRF验证:Django中POST请求必须携带CSRF令牌,否则会被拦截。

四、模型层校验确认

确保Favorie模型配置正确,避免重复添加同一件商品:

class Favorie(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    
    class Meta:
        unique_together = ('user', 'product') # 限制同一用户不能重复添加同一商品

内容的提问来源于stack exchange,提问作者Atoui Abderahman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:52:44