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
相关产品推荐
相关产品推荐

