Django电影应用:无法添加多部影片至Watchlist问题求助
问题排查与解决方案
核心问题分析
- 模型关系错误:
Watchlist模型中使用OneToOneField关联Movie,这意味着一部电影只能对应一个Watchlist实例,直接导致无法添加多部电影(无论同一用户还是不同用户)。 - Slug字段约束未处理:
Watchlist的slug字段设置了unique=True但未允许空值,且创建时未自动生成slug,会触发数据库唯一性错误,导致添加失败。 - 收藏判断逻辑失效:
add_watchlist视图中用filter返回的QuerySet直接与movie对象比较,永远无法正确检测当前用户是否已收藏该电影,且未过滤用户维度的收藏记录。 - 收藏列表数据混乱:
watchlist视图直接获取所有用户的收藏内容,而非当前登录用户的专属列表。
具体修复方案
1. 修改Watchlist模型
将一对一关系改为外键,添加用户-电影的唯一约束,自动生成slug:
from django.db import models from django.contrib.auth.models import User from Movies.models import Movie from django.utils.text import slugify class Watchlist(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) movie = models.ForeignKey(Movie, on_delete=models.CASCADE) slug = models.SlugField(unique=True, max_length=50, blank=True) date_added = models.DateField(auto_now_add=True) # 确保同一用户不会重复收藏同一部电影 class Meta: unique_together = ('user', 'movie') def save(self, *args, **kwargs): # 自动生成唯一slug if not self.slug: self.slug = slugify(f"{self.user.username}-{self.movie.name}")[:50] super().save(*args, **kwargs) def __str__(self): return f"{self.user.username}'s Watchlist: {self.movie.name}"
2. 修正Watchlist视图逻辑
修复添加、查询、删除的逻辑,加入登录验证和用户反馈:
from django.shortcuts import render, redirect from Movies.models import Movie from Watchlist.models import Watchlist from django.contrib import messages def watchlist(request): if not request.user.is_authenticated: messages.error(request, "请先登录查看收藏列表") return redirect('login') # 替换为你的登录URL名称 # 仅获取当前用户的收藏,用select_related优化查询 watchlist = Watchlist.objects.filter(user=request.user).select_related('movie') return render(request, 'watchlist.html', {'watch': watchlist}) def add_watchlist(request, p): if not request.user.is_authenticated: messages.error(request, "请先登录才能添加收藏") return redirect('login') movie = Movie.objects.get(id=p) # 检查当前用户是否已收藏该电影 if Watchlist.objects.filter(user=request.user, movie=movie).exists(): messages.info(request, "这部电影已经在你的收藏列表里了") else: try: Watchlist.objects.create(user=request.user, movie=movie) messages.success(request, "电影已添加到收藏列表") except Exception as e: messages.error(request, f"添加失败: {str(e)}") # 重定向回电影详情页(替换为实际的详情页URL名称) return redirect('Movies:movie_detail', p) def delete_watchlist(request, p): if not request.user.is_authenticated: messages.error(request, "请先登录才能删除收藏") return redirect('login') try: # 确保只能删除当前用户的收藏项 watch_item = Watchlist.objects.get(id=p, user=request.user) watch_item.delete() messages.success(request, "已从收藏列表移除") except Watchlist.DoesNotExist: messages.error(request, "该收藏项不存在") return redirect('Watchlist:view_watchlist')
3. 模板优化(可选)
在模板中添加消息提示组件(比如base.html):
{% if messages %} {% for message in messages %} <div class="alert alert-{{ message.tags }}"> {{ message }} </div> {% endfor %} {% endif %}
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

