当前位置: 首页 > news >正文

【Django】-8- 视图和模型的关联

一、🎉 评论和用户关联 (Model + 视图 + 关联建立)

1. 修改 Model :给评论加 “用户关联” 👥

from django.db import models
from django.contrib.auth.models import User  # 引入用户模型class Feedback(models.Model):# 关键!给评论关联用户user = models.ForeignKey(User,           # 关联的模型(用户表)default=1,      # 默认关联 ID=1 的用户(可根据需求改)on_delete=models.CASCADE,  # 用户被删,评论也跟着删)# 其他字段(质量、态度、速度等)quality = models.IntegerField()attitude = models.IntegerField()speed = models.IntegerField()text = models.TextField()anonymous = models.BooleanField()

① 软关联 vs 硬关联
  • ForeignKey 是 硬关联 :评论必须 “绑定” 一个真实用户(数据库里存用户 ID )。
  • 如果想做 “软关联”(比如存用户名但不严格绑定),可以用 CharField 存用户名,但推荐用 ForeignKey !

② default=1 :默认值
  • 用户没选关联时,默认关联到 ID=1 的用户(比如管理员)。
  • 可以改成 default=None ,但要处理 “空值” 逻辑~

③ on_delete=models.CASCADE :关联方删除怎么办?
  • 如果用户(关联方)被删了,评论(关联对象)也会 级联删除 (一起删掉)。
  • 其他选项:PROTECT(阻止删用户,报错)、SET_NULL(评论的 user 设为 null ,需允许 null )

④ 如何根据评论找用户?
  • 评论对象 → .user 直接拿到用户!

    feedback = Feedback.objects.get(id=1)
    print(feedback.user.username)  # 输出评论用户的用户名
    

⑤ 如何根据用户找评论?
  • 用户对象 → .feedback_set 拿到所有评论!

    user = User.objects.get(username="小明")
    user.feedback_set.all()  # 小明的所有评论
    

2. 修改视图:控制评论发布逻辑 🔍

判断用户是否已发布评论

from django.http import JsonResponsedef submit_feedback(request):# 1. 拿到当前登录用户user = request.user# 2. 检查用户是否已发布过评论obj_list = user.feedback_set.all()  # 用户的所有评论if obj_list:  # 已经发过评论return JsonResponse({"code": -1,"msg": "你已经发布过评论内容了"})# 3. 没发过 → 继续处理发布逻辑...

  • request.user :当前登录的用户(如果没登录,可能是匿名用户,需处理!)。
  • user.feedback_set.all() :Django 自动生成的 “反向关联”,拿到用户的所有评论。
  • 如果 obj_list 不为空 → 说明用户发过评论 → 返回错误,阻止重复发布!

3. 发布评论:和用户建立关联 🚀

发布时绑定用户

from .models import Feedback  # 引入评论模型def submit_feedback(request):# 假设前端传的数据在 data 里data = {"quality": 5,"attitude": 5,"speed": 5,"text": "服务超棒!","anonymous": False}# 关键!创建评论时,关联当前用户Feedback.objects.create(quality=data['quality'],attitude=data['attitude'],speed=data['speed'],text=data['text'],anonymous=data['anonymous'],user=request.user  # 绑定当前登录用户)return JsonResponse({"code": 0,"msg": "评论发布成功"})

  • user=request.user :发布评论时,直接把当前登录用户绑定到评论!
  • 这样评论就和用户 “锁死” 啦~ 后续可以通过 评论.user 找用户,或 用户.feedback_set 找评论!

完整小剧场 🎬

  1. 用户发布评论
    小明登录后,填评论表单 → 点 “提交” → 前端发请求到后端。

  2. 视图检查
    后端视图 submit_feedback → 用 request.user 拿到小明 → 检查 user.feedback_set.all() → 发现没发过评论。

  3. 创建评论并关联
    用 Feedback.objects.create(..., user=request.user) → 评论和小明绑定。

  4. 后续查询

    • 想找 “这条评论是谁发的” → 评论.user.username → 得到 “小明”。
    • 想找 “小明发过哪些评论” → 小明.feedback_set.all() → 得到所有评论。

必做小事:迁移数据库 🔧

改了 Model 后,必须执行命令,让数据库同步修改(修改模板需要迁移,而前端返回的data直接放到数据库)

二、🗄️ login 函数如何关联 User 表?数据库联动揭秘!

User 表是啥?数据库里的 “用户花名册”📖

 

Django 自带的 User 表(在数据库里通常叫 auth_user)就像图书馆的 “读者花名册”:

  • 每一行记录对应一个用户(比如 “小明、小红”)。
  • 字段包括 id(唯一编号,比如 101)、username(用户名)、password(加密后的密码)等。

当你用 User.objects.create_user(...) 创建 new_user 时:

  • 数据库的 auth_user 表会 新增一条新记录(比如 id=101, username="小明")。
  • new_user 就是这条记录在代码里的 “代言人”(模型实例)。

 

 

login 函数如何 “绑定” 数据库?3 步联动 ⚙️

 

第一步:从 new_user 里拿 “用户 ID”(花名册编号)

new_user 里藏着数据库 User 表的 id(比如 new_user.id=101),login 函数会先 “偷偷记下” 这个 ID:

# 源码里的关键操作(简化版)
user_id = new_user.id  # 拿到数据库里的用户编号,比如 101

类比:图书馆借书时,先查读者的 “会员卡编号”(对应 User 表的 id)。

 

第二步:把 “用户 ID” 存到 Session 表(借书登记本)

Django 有个专门的 django_session 表,像图书馆的 “借书登记本”,记录 “谁借了书”(谁登录了):
login 函数会在这个表里新增一条记录,内容是:

session_key: "随机字符串"  # 相当于“借书凭证号”
session_data: "用户ID=101, 认证方式=...",  # 存在用户 ID
expire_date: "2025-09-03"  # 过期时间(默认2周)

同时,浏览器会收到 sessionid="随机字符串" 的 Cookie(相当于把 “借书凭证号” 给用户揣着)。

 

第三步:后续请求时,通过 Session 找到 User 表记录

用户登录后访问其他页面(比如个人中心)时:

  1. 浏览器自动发送 sessionid="随机字符串"
  2. Django 用这个字符串查 django_session 表 → 找到 用户ID=101
  3. 用 用户ID=101 查 auth_user 表 → 找到对应的用户记录(小明)。
  4. 把 request.user 设为小明 → 视图函数就能用 request.user 访问他的信息啦~

 

小剧场:数据库联动全过程 🎭

  1. 注册用户
    调用 User.objects.create_user(...) → auth_user 表新增 id=101, username="小明" → new_user 代表这条记录。

  2. 调用 login
    login(request, new_user) → django_session 表新增一条记录:session_key="abc123", session_data="用户ID=101" → 浏览器收到 sessionid=abc123

  3. 访问个人中心

    • 浏览器发请求时带 sessionid=abc123
    • Django 查 django_session 表 → 得到 用户ID=101
    • 查 auth_user 表 → 找到 id=101 的小明 → request.user 变成小明。
    • 个人中心视图显示 “小明的个人信息”。

 

总结:三张表的 “合作舞蹈” 💃

  • auth_user 表:存用户的 “原始信息”(用户名、密码等)。
  • django_session 表:存 “登录状态”(哪个 sessionid 对应哪个用户 ID)。
  • login 函数:是 “牵线红娘”,把 new_user(对应 auth_user 记录)和 Session 表绑定,让后续请求能通过 sessionid 找到用户。

这就是 login 函数和数据库 User 表的 “暗箱操作”~ 全程自动,不用你手动写 SQL,Django 都帮你搞定啦! 🎉

三、🎭 为什么 login() 函数能 “召唤” 出 Session?

先回忆:Session 是啥?

Session 就像 “快递单号” :

  • 浏览器端:存着 sessionid=ABC123(类似快递单号贴在包裹上)。
  • 服务器端:django_session 表存着 “单号 ABC123 对应用户小明”(类似快递柜系统记录)。

有了这个 “单号”,服务器才能记住 “谁登录过”~

 

login() 函数里藏着 “创建 Session 的密码”🔑

看 Django 源码的核心代码(简化版):

def login(request, user):# 1. 生成用户的 Session 信息(包含用户 ID 等)request.session[SESSION_KEY] = user.id  # 存用户 ID 到 Sessionrequest.session[BACKEND_SESSION_KEY] = "默认认证方式"request.session[HASH_SESSION_KEY] = user.get_session_auth_hash()  # 安全校验码# 2. 标记 Session 被修改了,必须保存到数据库!request.session.modified = True  # 这一步是关键!

关键在这两行代码:

  1. request.session[SESSION_KEY] = user.id

    • 作用:往 request.session 里 “写数据”(比如用户 ID)。
    • 类比:在快递单上写下 “收件人 = 小明”,这张单子就有了实际意义。
  2. request.session.modified = True

    • 作用:告诉 Django“这个 Session 被改过了,赶紧存到数据库里!”
    • 类比:快递单填完后,喊一声 “快递员快来取!”,单子就被正式入系统了。

 

Django 的 “自动保存机制” 在帮忙 🤖

Django 有个 “Session 中间件”django.contrib.sessions.middleware.SessionMiddleware),它会在请求结束时自动检查:

  • 如果 request.session.modified 是 True → 立刻把 Session 数据存到数据库(django_session 表)。
  • 同时给浏览器发 sessionid Cookie(相当于快递单号给用户)。

 

小剧场:login() 创建 Session 的全过程 🎬

  1. 调用 login(request, new_user)
    函数执行 → 往 request.session 里写入 user.id=101 → 设 request.session.modified = True

  2. 中间件出手
    请求处理快结束时,Session 中间件检查到 modified=True → “哎呀,Session 改了,赶紧存!”

  3. 数据库新增记录
    django_session 表新增一行:session_key="ABC123", session_data="用户ID=101..."

  4. 浏览器收到 Cookie
    响应里带着 Set-Cookie: sessionid=ABC123 → 浏览器存起来,下次访问自动带上。

 

总结:login() 是 “触发者”,中间件是 “执行者”

login() 函数本身不直接创建 Session,而是通过:

  1. 往 request.session 写数据 → 2. 标记 modified=True → 3. 触发中间件自动保存到数据库。

就像你在快递单上填好信息并喊 “发货”,快递系统(中间件)就自动帮你完成后续流程~ 这就是 Django 封装的 “懒人福利” 呀! 😎

 

四、🔍 feedback_set.all() 藏在哪里?

先看 “诞生条件”:外键是前提 🔗

feedback_set 不是凭空出现的,必须满足这个条件:
你的评论模型(比如 Feedback)里,有一个外键字段关联了 User 模型:

# models.py 里的评论模型
from django.db import models
from django.contrib.auth.models import Userclass Feedback(models.Model):# 关键!外键关联 User 模型user = models.ForeignKey(User, on_delete=models.CASCADE)content = models.TextField()  # 评论内容

有了这个外键,Django 会 自动给 User 模型 “附加” 一个 feedback_set 属性,用来存放这个用户的所有评论~

 

藏在 “用户对象” 里:随用户出现 🧑💻

feedback_set.all() 必须通过 具体的用户对象 调用,比如:

1. 从数据库查一个用户

from django.contrib.auth.models import User# 查一个用户(比如 ID=1 的用户)
user = User.objects.get(id=1)# 调用 feedback_set.all() → 拿到这个用户的所有评论
user_comments = user.feedback_set.all()  # 🌟 在这里!

 

2. 用当前登录用户(request.user

在视图函数里,通过 request.user 拿到登录用户,再调用它:

# views.py 里的视图函数
def my_comments(request):# 当前登录用户(已登录状态)current_user = request.user# 拿到该用户的所有评论user_comments = current_user.feedback_set.all()  # 🌟 也在这里!return render(request, 'my_comments.html', {'comments': user_comments})

 

为什么叫 feedback_set?可以改名吗? 📛

  • 名字是 Django 自动生成的:小写模型名 + _set(评论模型是 Feedback → 小写是 feedback → 所以叫 feedback_set)。
  • 想改个好听的名字?可以在定义外键时加 related_name
class Feedback(models.Model):user = models.ForeignKey(User, on_delete=models.CASCADE,related_name="my_comments"  # 自定义名字!)

之后就可以用新名字调用啦:

user.my_comments.all()  # 是不是更顺口~

 

小剧场:feedback_set.all() 的工作日常 🎭

  1. 用户发评论
    小明(user.id=1)发了 2 条评论 → 数据库 Feedback 表中,这两条评论的 user_id 都是 1。

  2. 调用 feedback_set.all()
    后端代码 user = User.objects.get(id=1) → 拿到小明的用户对象 → 调用 user.feedback_set.all()

  3. 返回结果
    Django 自动去 Feedback 表查 user_id=1 的所有记录 → 返回这 2 条评论 → 可以在模板里循环显示啦~

 

总结:feedback_set.all() 藏在 “用户对象” 里

它是 Django 给外键关联自动生成的 “评论集合工具”,必须通过 具体用户对象 调用,用来快速获取该用户的所有评论~

记住:有外键关联才有它,通过用户对象才能找到它! 😊

http://www.dtcms.com/a/313298.html

相关文章:

  • Linux下Redis常用命令
  • Java线程安全类设计思路总结
  • 深入理解Python的`__missing__`方法:动态处理字典中不存在的键: Effective Python 第18条
  • 网络规划与设计5个阶段内容
  • 大模型学习--第一天
  • Linux命令基础(上)
  • day 44 文件的规范书写与拆分
  • LCL滤波器及其电容电流前馈有源阻尼设计软件【LCLAD_designer】
  • 机器学习——决策树(DecisionTree)
  • 分享两个问题及其解决方法:发送AT没反应和wifi模块连接不上热点
  • Java设计模式之行为型模式(访问者模式)应用场景分析
  • MATLAB小波分析工具包进行时间序列的小波功率谱分析
  • 基于Matlab的深度学习智能行人检测与统计系统
  • FastAPI入门:安全性
  • 网安-逻辑漏洞-23登陆验证
  • 【系统编程】错误处理、读写缓冲区及位图
  • 文章分享---《Keil 再升级,修复了这些bug》
  • [自动化Adapt] 录制引擎
  • Nginx 相关实验(1)
  • C语言数据结构(7)贪吃蛇项目2.贪吃蛇项目实现
  • 分离还是统一,这是个问题
  • STM32F103_Bootloader程序开发13 - 巧用逆向拷贝,实现固件更新的“准原子”操作,无惧升级中的意外掉电
  • 时间空间复杂度
  • 高质量数据集|从武汉光谷《面向科技情报大模型的高质量数据集建设》招标项目谈起
  • 实现游戏排行榜
  • SpringBoot项目数据脱敏(自定义注解)
  • 关于corn
  • SpringAI无人机智能灌溉、本地化AI推理、分析气象站、分析球场草皮系统实践
  • Python操作Excel——从入门到精通
  • QML 将一个qml文件定义为公共的全局单例