如何修改Django代码禁止用户关注自身?已试unique_together无效
解决Django关注列表禁止用户关注自己的问题
嘿,我明白你遇到的问题了——unique_together确实不适合这个场景,因为它是用来约束字段组合的唯一性,而我们需要的是禁止用户把自己加入关注列表的业务逻辑验证。下面给你两种可靠的解决方案,从视图层和模型层分别处理,确保万无一失:
方案一:视图层直接校验(适配你的按钮触发场景)
既然你是通过其他用户个人页面的按钮来添加关注,那在处理请求的视图里直接做校验是最直观的方式,能在请求入口就拦截非法操作:
from django.shortcuts import get_object_or_404, redirect from django.contrib.auth.decorators import login_required from django.contrib import messages from .models import FollowList, User @login_required def follow_user(request, user_id): target_user = get_object_or_404(User, id=user_id) # 核心校验:禁止关注自己 if target_user == request.user: messages.error(request, "你不能关注自己哦!") return redirect('user_profile', user_id=user_id) # 获取当前用户的FollowList,不存在则自动创建(因为是OneToOne关联) follow_list, created = FollowList.objects.get_or_create(user=request.user) # Django的ManyToMany会自动处理重复添加,无需额外判断 follow_list.following.add(target_user) messages.success(request, f"你已成功关注{target_user.username}!") return redirect('user_profile', user_id=user_id)
这个方法简单直接,和你通过按钮触发的使用场景完美匹配,用户操作时能立刻得到反馈。
方案二:模型层全局验证(避免其他入口的误操作)
如果担心后台管理、脚本等其他入口可能误添加自己为关注对象,那在模型层做全局验证更安全。这里提供两种实现方式:
方式1:封装自定义添加方法
在FollowList模型里写一个专门的方法来处理关注逻辑,把校验逻辑封装进去,所有添加操作都调用这个方法:
from django.db import models from django.contrib.auth.models import User from django.core.exceptions import ValidationError class FollowList(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True) following = models.ManyToManyField(User, related_name='followers') def add_following(self, target_user): if target_user == self.user: raise ValidationError("不能关注自己!") # 自动去重,无需额外判断是否已关注 self.following.add(target_user)
之后在视图里就可以这样调用:
follow_list, created = FollowList.objects.get_or_create(user=request.user) try: follow_list.add_following(target_user) messages.success(request, f"你已成功关注{target_user.username}!") except ValidationError as e: messages.error(request, str(e))
方式2:用信号拦截非法操作
如果想更底层地拦截所有修改following字段的操作,可以用m2m_changed信号,在多对多关系变更时触发校验:
from django.db.models.signals import m2m_changed from django.dispatch import receiver from django.core.exceptions import ValidationError from .models import FollowList @receiver(m2m_changed, sender=FollowList.following.through) def prevent_self_follow(sender, instance, action, pk_set, **kwargs): # 只在添加操作时触发校验 if action == 'pre_add': # 检查待添加的用户ID里是否包含当前用户自己的ID if instance.user.id in pk_set: raise ValidationError("不能关注自己!")
这种方式能拦截所有修改following字段的操作,包括后台管理界面的操作,安全性拉满。
为什么unique_together没用?
补充说明一下:unique_together是用来确保多个字段的组合在表中唯一,比如限制A不能重复关注B时可以用它,但你现在的需求是A不能关注A,这是单对象的逻辑校验,和字段组合唯一性无关,所以unique_together自然起不了作用。
内容的提问来源于stack exchange,提问作者xsmac
相关产品推荐
相关产品推荐

