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

Django电影应用:无法添加多部影片至Watchlist问题求助

问题排查与解决方案

核心问题分析

  1. 模型关系错误:Watchlist模型中使用OneToOneField关联Movie,这意味着一部电影只能对应一个Watchlist实例,直接导致无法添加多部电影(无论同一用户还是不同用户)。
  2. Slug字段约束未处理:Watchlist的slug字段设置了unique=True但未允许空值,且创建时未自动生成slug,会触发数据库唯一性错误,导致添加失败。
  3. 收藏判断逻辑失效:add_watchlist视图中用filter返回的QuerySet直接与movie对象比较,永远无法正确检测当前用户是否已收藏该电影,且未过滤用户维度的收藏记录。
  4. 收藏列表数据混乱: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:33:10