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

如何防止同一电影重复添加至Django Watchlist

解决Django观影清单重复添加问题

问题根源

原代码的add_watchlist视图存在两个核心问题:

  • 检查逻辑错误:Watchlist.objects.all()获取的是所有用户的观影记录,且直接用movie not in watchlist判断无效(watchlist是Watchlist对象集合,不是Movie对象)
  • 数据库层面无约束:即使视图逻辑修复,也可能因并发等情况出现重复数据

解决方案

1. 给Watchlist模型添加联合唯一约束

修改Watchlist模型,确保同一用户同一电影只能存在一条记录,从数据库层面杜绝重复:

from django.db import models
from django.contrib.auth.models import User
from Movies.models import Movie

class Watchlist(models.Model):
    user=models.ForeignKey(User,on_delete=models.CASCADE)
    movie=models.ForeignKey(Movie,on_delete=models.CASCADE)
    quantity=models.IntegerField(default=1)
    date=models.DateField(auto_now_add=True)

    # 添加联合唯一约束(Django ≥2.2推荐写法)
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['user', 'movie'], name='unique_user_movie_watchlist')
        ]
        # 兼容Django<2.2版本可替换为:
        # unique_together = ('user', 'movie')

    def __str__(self):
        return self.movie.name

2. 修复add_watchlist视图逻辑

修改视图中的检查逻辑,仅查询当前用户的观影记录,同时处理可能的重复添加场景:

from django.shortcuts import render,redirect
from Movies.models import Movie
from Watchlist.models import Watchlist
from django.contrib import messages
from django.db import IntegrityError

def add_watchlist(request,p):
    user=request.user
    movie=Movie.objects.get(id=p)
    
    try:
        # 尝试创建记录,若已存在会触发IntegrityError异常
        Watchlist.objects.create(user=user, movie=movie)
        messages.success(request, f"{movie.name} 已添加至观影清单")
    except IntegrityError:
        # 捕获重复添加异常,提示用户
        messages.info(request, f"{movie.name} 已在你的观影清单中")
    finally:
        return redirect('Watchlist:view_watchlist')

3. 可选优化:提前检查避免异常

如果不想依赖异常捕获,也可以先查询当前用户是否已添加该电影:

def add_watchlist(request,p):
    user=request.user
    movie=Movie.objects.get(id=p)
    
    # 仅查询当前用户的观影记录,判断是否已存在
    if not Watchlist.objects.filter(user=user, movie=movie).exists():
        Watchlist.objects.create(user=user, movie=movie)
        messages.success(request, f"{movie.name} 已添加至观影清单")
    else:
        messages.info(request, f"{movie.name} 已在你的观影清单中")
    
    return redirect('Watchlist:view_watchlist')

补充说明

  • 添加messages提示可以让用户明确知晓操作结果,提升交互体验
  • 模型层的唯一约束是最后一道防线,确保数据一致性,即便视图逻辑出现疏漏也不会产生重复数据
  • 原视图中watchlist=Watchlist.objects.all()的逻辑完全错误,既未过滤当前用户,也无法直接通过movie in watchlist判断(需对比每个Watchlist对象的movie字段)

内容的提问来源于stack exchange,提问作者Miguel O'Hara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:57:52