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

Django实现登录用户收藏食品并在个人面板展示功能求助

修复收藏功能实现步骤

先梳理现有代码里的问题:模型字段命名不规范、视图未过滤当前用户、模板变量名错误、缺少收藏/取消收藏的处理逻辑和前端交互。下面一步步修正:

1. 修正模型代码

现有模型的字段名带_id不符合Django惯例(Django会自动为ForeignKey生成_id后缀的数据库字段),而且__str__方法引用了不存在的name字段,修正如下:

from django.db import models
from django.conf import settings

class Favorite(models.Model):
    # 去掉字段名的_id,直接用关联模型名作为字段名
    consumable = models.ForeignKey(Consumable, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    def __str__(self):
        # 返回有意义的字符串,关联用户和食品名称
        return f"{self.user.username} - {self.consumable.name}"

    # 加唯一约束,避免同一用户重复收藏同一食品
    class Meta:
        unique_together = ('user', 'consumable')

2. 完善视图代码

2.1 个人面板视图(dashboard)

原视图没有过滤当前登录用户的收藏,还做了没必要的循环创建Consumable对象,修正后:

from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from .models import Favorite

@login_required  # 强制用户登录才能访问面板
def dashboard(request):
    # 只获取当前登录用户的收藏,用select_related优化查询,减少数据库请求
    favorites = Favorite.objects.filter(user=request.user).select_related('consumable').order_by('-id')
    return render(request, 'accounts/dashboard.html', {'favorites': favorites})

2.2 新增收藏视图(add_favorite)

处理前端的收藏请求,需要AJAX支持:

from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from .models import Consumable, Favorite

@login_required
def add_favorite(request):
    if request.method == 'POST':
        consumable_id = request.POST.get('consumable_id')
        consumable = get_object_or_404(Consumable, id=consumable_id)
        # 检查是否已经收藏,避免重复创建
        if not Favorite.objects.filter(user=request.user, consumable=consumable).exists():
            Favorite.objects.create(user=request.user, consumable=consumable)
            return JsonResponse({'status': 'success', 'message': 'Added to favorites'})
        return JsonResponse({'status': 'info', 'message': 'Already in favorites'})
    return JsonResponse({'status': 'error', 'message': 'Invalid request method'})

2.3 新增取消收藏视图(remove_favorite)

处理面板里的删除按钮请求:

@login_required
def remove_favorite(request, consumable_id):
    if request.method == 'POST':
        consumable = get_object_or_404(Consumable, id=consumable_id)
        Favorite.objects.filter(user=request.user, consumable=consumable).delete()
        return JsonResponse({'status': 'success', 'message': 'Removed from favorites'})
    return JsonResponse({'status': 'error', 'message': 'Invalid request method'})

3. 调整模板代码

3.1 收藏按钮模板

给按钮添加食品ID的data属性,添加AJAX交互代码:

<div class="fav-me">
  <hr />
  <!-- 传递当前食品的ID到按钮的data属性 -->
  <button id="fav-btn" data-consumable-id="{{ consumable.id }}">Favorite Me</button>
</div>

<script>
document.getElementById('fav-btn').addEventListener('click', function() {
    const consumableId = this.dataset.consumableId;
    fetch('{% url "add_favorite" %}', {
        method: 'POST',
        headers: {
            'X-CSRFToken': '{{ csrf_token }}',  // Django需要CSRF令牌
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: `consumable_id=${consumableId}`
    })
    .then(response => response.json())
    .then(data => {
        // 可以在这里添加提示,比如弹窗或者按钮状态变化
        alert(data.message);
        // 比如把按钮改成"Added"并禁用
        if (data.status === 'success') {
            this.textContent = 'Added to Favorites';
            this.disabled = true;
        }
    })
    .catch(error => console.error('Error:', error));
});
</script>

3.2 个人面板模板

修正变量名错误,添加删除按钮的交互:

<div class="dash-header">
  <h2>Your favorite items</h2>
  <div class="fav-item">
   {% if favorites %}
    {% for favorite in favorites %}
    <div class="single-fav">
        <h4>Name: {{ favorite.consumable.name }}</h4>
        <p>${{ favorite.consumable.price }}</p>
        <!-- 删除按钮,传递食品ID -->
        <button class="remove-fav-btn" data-consumable-id="{{ favorite.consumable.id }}">X</button>
    </div>
    {% endfor %}
   {% else %}
    <p>You don't have any favorites</p>
   {% endif %}
  </div>
</div>

<script>
// 批量绑定删除按钮的点击事件
document.querySelectorAll('.remove-fav-btn').forEach(button => {
    button.addEventListener('click', function() {
        const consumableId = this.dataset.consumableId;
        fetch(`{% url "remove_favorite" consumable_id=0 %}`.replace('0', consumableId), {
            method: 'POST',
            headers: {
                'X-CSRFToken': '{{ csrf_token }}',
            }
        })
        .then(response => response.json())
        .then(data => {
            alert(data.message);
            // 删除当前DOM元素
            this.closest('.single-fav').remove();
            // 如果删除后没有收藏了,显示空状态
            if (!document.querySelector('.single-fav')) {
                document.querySelector('.fav-item').innerHTML = '<p>You don\'t have any favorites</p>';
            }
        })
        .catch(error => console.error('Error:', error));
    });
});
</script>

4. 配置URL路由

在项目的urls.py里添加对应的路由:

from django.urls import path
from . import views

urlpatterns = [
    path('dashboard/', views.dashboard, name='dashboard'),
    path('add-favorite/', views.add_favorite, name='add_favorite'),
    path('remove-favorite/<int:consumable_id>/', views.remove_favorite, name='remove_favorite'),
    # 其他现有路由...
]

这样整个收藏功能就可以正常运作了:登录用户点击"Favorite Me"按钮会异步添加收藏到个人面板,面板里能看到自己的所有收藏,还能删除任意收藏项。

内容的提问来源于stack exchange,提问作者Michael Plantamura

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:35:40