0

0

Django模型设计:实现用户专属交互(以点赞功能为例)

DDD

DDD

发布时间:2025-11-28 13:22:27

|

786人浏览过

|

来源于php中文网

原创

Django模型设计:实现用户专属交互(以点赞功能为例)

在django中,为模型添加用户专属的布尔状态(如点赞)不能直接在主模型上实现。正确的做法是引入一个中间模型,通过外键关联用户和目标对象,并在此中间模型中存储该用户对该对象的特定状态,确保数据的独立性和准确性。

在开发Web应用时,我们经常会遇到需要为用户提供个性化交互功能的场景,例如用户对文章的点赞、收藏或关注。一个常见的误区是尝试在主对象模型(例如 Post 模型)中直接添加一个布尔字段来表示某个用户是否“喜欢”了它。然而,这种方法是不可行的,因为模型字段是共享的属性,一旦一个用户改变了该字段的值,所有其他用户都会看到相同的变化,这显然不符合用户专属的交互逻辑。

问题分析:为什么不能直接在主模型上添加布尔字段?

假设我们有一个 Post 模型,并且我们尝试添加一个 is_liked 布尔字段:

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    # is_liked = models.BooleanField(default=False) # 错误的做法!

如果User A将 post.is_liked 设置为 True,那么对于User B,post.is_liked 也会显示为 True,这与我们希望的“User A喜欢,User B可能不喜欢”的逻辑相悖。我们需要的是一个能够记录“哪个用户喜欢了哪篇文章”的关系,而不是文章本身的一个通用属性。

解决方案:引入中间模型

解决此类用户专属交互问题的标准方法是引入一个中间模型(或称关联模型),来明确地表示用户与对象之间的多对多关系,并在此关系中存储具体的交互状态。对于点赞功能,我们可以创建一个 PostLike 模型,它将 User 模型和 Post 模型关联起来。

实现步骤:

  1. 定义中间模型 PostLike:

    这个模型将包含两个外键:一个指向 User 模型(Django内置的用户模型),另一个指向 Post 模型。

    from django.db import models
    from django.contrib.auth.models import User # 导入Django的用户模型
    
    # 假设你已经有一个Post模型
    class Post(models.Model):
        title = models.CharField(max_length=200)
        content = models.TextField()
    
        def __str__(self):
            return self.title
    
    class PostLike(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="点赞用户")
        post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes', verbose_name="点赞文章")
    
        class Meta:
            # 确保每个用户只能点赞同一篇文章一次
            unique_together = ('user', 'post')
            verbose_name = "文章点赞"
            verbose_name_plural = "文章点赞"
    
        def __str__(self):
            return f"{self.user.username} 喜欢了 {self.post.title}"
    • user = models.ForeignKey(User, on_delete=models.CASCADE):表示哪个用户进行了点赞操作。当用户被删除时,其所有点赞记录也应被删除。
    • post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes'):表示哪篇文章被点赞。related_name='likes' 允许我们通过 post.likes.all() 方便地获取某篇文章的所有点赞记录。
    • class Meta: unique_together = ('user', 'post'):这是关键一步。它确保了 user 和 post 的组合在数据库中是唯一的,从而防止同一个用户重复点赞同一篇文章。
  2. 进行数据库迁移:

    定义模型后,需要运行Django的迁移命令来创建数据库表:

    python manage.py makemigrations
    python manage.py migrate

如何使用 PostLike 模型:

  • 用户点赞文章:

    一帧秒创
    一帧秒创

    基于秒创AIGC引擎的AI内容生成平台,图文转视频,无需剪辑,一键成片,零门槛创作视频。

    下载

    当用户点击“点赞”按钮时,创建一个 PostLike 实例。

    from django.shortcuts import get_object_or_404
    from django.http import HttpResponse
    from django.contrib.auth.decorators import login_required
    
    @login_required
    def like_post(request, post_id):
        post = get_object_or_404(Post, id=post_id)
        # get_or_create 方法可以避免重复创建,并返回 (object, created)
        like, created = PostLike.objects.get_or_create(user=request.user, post=post)
        if created:
            return HttpResponse("点赞成功!")
        else:
            return HttpResponse("您已经点赞过这篇文章了。")
  • 检查用户是否已点赞某篇文章:

    在渲染文章详情页时,判断当前用户是否已点赞。

    def post_detail(request, post_id):
        post = get_object_or_404(Post, id=post_id)
        is_liked_by_user = False
        if request.user.is_authenticated:
            is_liked_by_user = PostLike.objects.filter(user=request.user, post=post).exists()
    
        # 将 is_liked_by_user 传递给模板进行渲染
        context = {
            'post': post,
            'is_liked_by_user': is_liked_by_user,
            'like_count': post.likes.count() # 获取点赞总数
        }
        # 通常会渲染一个模板,例如:
        # return render(request, 'post_detail.html', context)
        return HttpResponse(f"文章:{post.title},当前用户是否点赞:{is_liked_by_user},总点赞数:{post.likes.count()}")
  • 用户取消点赞:

    当用户点击“取消点赞”按钮时,删除对应的 PostLike 实例。

    @login_required
    def unlike_post(request, post_id):
        post = get_object_or_404(Post, id=post_id)
        # delete 方法返回 (删除的记录数, {每个模型的删除数})
        deleted_count, _ = PostLike.objects.filter(user=request.user, post=post).delete()
        if deleted_count > 0:
            return HttpResponse("取消点赞成功。")
        else:
            return HttpResponse("您尚未点赞此文章。")

总结与注意事项:

通过引入中间模型 PostLike,我们成功地解决了在Django中实现用户专属交互状态的问题。这种模式不仅适用于点赞功能,还可以推广到收藏、关注、评分等多种用户与对象之间的个性化关系。

关键点回顾:

  • 中间模型: 用于连接两个或多个模型,并存储它们之间关系的特定数据。
  • ForeignKey: 建立模型间的关联。
  • related_name: 方便反向查询,提高代码可读性。例如,通过 post.likes.all() 可以获取所有点赞记录。
  • unique_together: 确保关系(如用户-文章点赞)的唯一性,防止数据冗余和逻辑错误。
  • 可扩展性: 如果将来需要记录点赞时间、点赞类型等额外信息,可以直接在 PostLike 模型中添加字段,而无需修改 Post 或 User 模型。

这种设计模式是Django模型关系管理中的一个核心概念,理解并熟练运用它对于构建健壮、可扩展的Web应用至关重要。

相关专题

更多
class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

465

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

13

2025.12.06

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

348

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2074

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

347

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

323

2023.10.09

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

410

2023.10.16

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 4.2万人学习

Django 教程
Django 教程

共28课时 | 3.2万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号