Django中不删除整行仅删除字段关联数据及remove报错如何解决
问题解决:Django移除Post关联的点赞用户报错
错误原因
你当前定义的liked_by字段是ForeignKey类型,该类型表示一对多关联,即一个Post实例的liked_by只能存储单个User对象的外键,本质是单值字段,不是集合类型,只有ManyToManyField(多对多字段)才支持add()、remove()这类集合操作方法,所以你调用remove才会触发属性不存在的报错。
解决方案
方案1(推荐,符合点赞业务逻辑):将liked_by改为多对多字段
正常业务场景下一个帖子可以被多个用户点赞,因此应该用ManyToManyField替换原有ForeignKey:
步骤1:修改models.py中字段定义
class Post(models.Model): content = models.CharField(max_length=140) date_created = models.DateTimeField(auto_now_add=True) poster = models.ForeignKey(User, on_delete=models.CASCADE) # 移除原有单独存储的likes字段,后续直接通过关联关系计数即可,避免数据不一致 # likes = models.IntegerField(default=0) # 改为多对多字段 liked_by = models.ManyToManyField( User, related_name='liked_posts', blank=True ) def serialize(self): return { "id": self.id, "poster": self.poster.username, "poster_image_url": self.poster.image_url, "date_created": self.date_created.strftime("%b %d %Y, %I:%M %p"), "content": self.content, # 直接通过多对多关联计数获取点赞数 "likes": self.liked_by.count(), }
步骤2:修改views.py中逻辑
@csrf_exempt def get_post(request, post_id): post = Post.objects.get(pk=post_id) if request.method == "GET": return JsonResponse(post.serialize()) elif request.method == "PUT": data = json.loads(request.body) # 建议直接传是否点赞的布尔值,不需要传点赞数避免前端恶意篡改 if data.get('is_like') is not None: if data['is_like']: # 点赞:添加当前用户到关联集合 post.liked_by.add(request.user) else: # 取消点赞:从关联集合移除当前用户 post.liked_by.remove(request.user) post.save() return HttpResponse(status=204)
步骤3:生成并执行数据库迁移
执行命令:
python manage.py makemigrations python manage.py migrate
方案2(不推荐,仅适配现有字段逻辑):直接清空外键字段
如果你坚持保留ForeignKey的定义(仅支持一个用户点赞),只需要把移除用户的代码改为给字段赋值None即可:
else: post.likes = data['likes'] # 替换原有的post.liked_by.remove(request.user) post.liked_by = None
该方案只会清空当前Post的点赞用户字段,不会删除Post本身。
内容的提问来源于stack exchange,提问作者Omayer Hasan
相关产品推荐
相关产品推荐

