如何设计最优的点赞功能Django模型,满足登录用户点赞帖子需求
方案对比与最优选择
你写的两个方案本质上底层逻辑是一致的:Django 中的 ManyToManyField 默认会自动生成一个和方案二结构相同的中间关联表,用来存储帖子和用户的点赞对应关系,二者的差异仅在于是否支持自定义扩展。
两个方案的适用场景
方案一:仅需要基础点赞功能时的最优选择
如果你只需要实现点赞、取消点赞、判断用户是否点赞、查询点赞总数这些基础需求,直接用方案一即可,Django 已经封装好了所有常用操作,代码量最少,维护成本最低:# 点赞 post.likes.add(request.user) # 取消点赞 post.likes.remove(request.user) # 判断当前用户是否已点赞 is_liked = post.likes.filter(id=request.user.id).exists() # 获取点赞总数 like_num = post.likes.count()完全可以满足你提到的「已登录用户点赞、计数加1」的需求。
方案二:需要扩展点赞属性时的选择
如果你后续需要存储点赞相关的额外信息,比如点赞时间、点赞用户IP、是否为匿名点赞、软删除标记等,就必须用显式创建中间表的方案二。你也可以把两种方案结合,用through参数关联自定义中间表,既保留 Django 多对多字段的封装能力,又支持自定义扩展:from django.db import models from django.conf import settings class Post(models.Model): title = models.CharField(max_length=255) # 通过through参数指定自定义中间表 likes = models.ManyToManyField(settings.AUTH_USER_MODEL, through="Like") # 高并发场景建议加冗余计数字段,避免每次count查询关联表 like_count = models.PositiveIntegerField(default=0) class Like(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) # 自定义扩展字段:点赞时间 created_at = models.DateTimeField(auto_now_add=True) class Meta: # 必须加联合唯一约束,避免同一个用户对同一个帖子重复点赞 constraints = [ models.UniqueConstraint(fields=['post', 'user'], name='unique_post_user_like') ]
高并发场景优化方案
如果你的站点访问量较高,每次查询点赞数都调用 count() 遍历关联表会带来较大的性能开销,建议给 Post 模型加 冗余点赞计数字段,也就是上面代码里的 like_count,通过 Django 信号或者重写 save/delete 方法同步更新计数值:
- 新增点赞记录时,
post.like_count += 1并保存 - 删除点赞记录时,
post.like_count -= 1并保存
查询点赞数时直接读取该字段即可,性能提升非常明显。
内容的提问来源于stack exchange,提问作者D_P
相关产品推荐
相关产品推荐

