【Django】-5- ORM的其他用法
一、🚀 ORM 新增数据魔法!
核心目标
教你用 Django ORM 给数据库 新增数据 !就像给数据库 “生小数据宝宝”👶
方法 1:实例化 Model + save(一步步喂数据)
obj = Feedback() # 实例化
obj.quality = data['quality'] # 指定数据
obj.attitude = data['attitude']
obj.speed = data['speed']
obj.text = data['text']
obj.anonymous = data['anonymous']obj.save() # 入库
1. obj = Feedback()
→ 造一个空数据盒子
Feedback
是模型类(模具),obj
是用模具做的 空数据模型 ~- 类比:用 “Feedback 模具” 捏一个空白小泥人,准备填数据~
2. obj.quality = data['quality']
→ 给盒子填数据
- 从
data
字典里,把quality
(商品质量)的值,塞给obj
的quality
字段~ - 后面几行同理:依次填
attitude
(客服态度)、speed
(物流速度)、text
(评论)、anonymous
(是否匿名)~ - 类比:给小泥人画眼睛、穿衣服、写名字… 每个属性都从
data
里选材料~
3. obj.save()
→ 把盒子存进数据库
- 填完所有数据后,调用
save()
方法,Django 会把obj
转换成 数据库的一条记录 ,永久保存! - 类比:把捏好、画好的小泥人,放进 “数据库展示柜” 里~
方法 2:类方法 create(一键批量填数据)
Feedback.objects.create(**data)
1. Feedback.objects
→ 模型的 “数据管家”
objects
是 Django 模型默认的 管理器 ,负责和数据库交互(增删查改)~- 类比:
Feedback
模型的 “专属小管家”,帮你处理数据操作~
2. .create(**data)
→ 一键创建 + 保存
create
是管家提供的 “快捷魔法”:自动帮你 实例化模型 + 填数据 + 保存入库 !**data
是把data
字典 “拆包”,把里面的键值对(如quality=5
、text="好评"
)传给create
方法~- 类比:告诉小管家
data
里的所有材料,它会自动用 “Feedback 模具” 捏好小泥人,直接放进展示柜!
3. 和方法 1 的区别
- 方法 1 是 手动一步步填数据 ,适合需要 “填数据前做额外操作” 的场景(比如给某个字段加默认值、校验)。
- 方法 2 是 一键批量操作 ,适合数据已经准备好,直接入库的场景,代码更简洁~
总结(小剧场对比)
方法 1 小剧场
你:管家!我要存一条反馈数据~
管家:好呀!先拿一个空盒子(Feedback()
)~
你:给盒子填质量、态度、速度…(手动赋值)
你:填好啦!放进展示柜(save()
)~
方法 2 小剧场
你:管家!我要存一条反馈数据,材料都在 data
里~
管家:收到!自动用模具捏好、填数据、放进展示柜(create(**data)
)~
两种方法都能给数据库新增数据,根据场景选就行啦~ 方法 1 灵活可控,方法 2 快捷方便! 🎉
(比如需要校验数据、加默认值 → 选方法 1;数据直接能用 → 选方法 2~)
二、🎯 Django ORM 修改数据
核心目标
教你用 Django ORM 给数据库 修改已有数据 !就像给数据库里的 “数据宝宝” 换衣服~ 👚
方法 1:修改实例对象(一步步改)
# 1. 获取数据
obj: Feedback = Feedback.objects.get(id=5) # 获取ID=5的数据
print(f"{obj=}, {obj.text}")# 2. 修改字段
obj.text = "7777"# 3. 保存修改
obj.save() # 重新入库
print(f"{obj=}, {obj.text}")
1. obj = Feedback.objects.get(id=5)
→ 找到要改的数据
Feedback.objects
是模型的 “数据管家”,get(id=5)
是让管家 找到 “ID=5” 的数据 ,赋值给obj
~- 类比:你对管家说 “把展示柜里 ID=5 的小泥人拿出来”,管家找到后给你~
2. print(...)
→ 看看原来的数据
- 打印
obj
和obj.text
,看看修改前的数据长啥样~ - 类比:拿到小泥人后,先看看它原来的衣服、装饰~
3. obj.text = "7777"
→ 给数据换 “新衣服”
- 把
obj
的text
字段改成"7777"
,其他字段不变~ - 类比:给小泥人换一件新衣服(只改
text
,其他装饰保留)~
4. obj.save()
→ 把修改后的数据放回数据库
- 调用
save()
,Django 会把修改后的obj
重新存回数据库,覆盖原来的数据~ - 类比:给小泥人换好新衣服后,放回展示柜(数据库)~
5. 再 print(...)
→ 看看修改后的数据
- 打印修改后的
obj
和obj.text
,确认修改生效~ - 类比:放回展示柜前,再检查一下小泥人的新衣服~
方法 2:调用类方法 update(批量改)
Feedback.objects.update(text="888")
1. Feedback.objects
→ 模型的 “数据管家”
- 还是那个 “专属小管家”,负责和数据库交互~
2. .update(text="888")
→ 批量修改数据
update
是管家提供的 “批量魔法”: 把所有数据的text
字段改成"888"
!- 注意:这会修改 所有数据 的
text
字段(如果想改指定数据,需要加过滤条件,比如filter(id=5).update(...)
)~ - 类比:你对管家说 “把展示柜里所有小泥人的衣服都换成
text="888"
样式”,管家会批量操作!
3. 和方法 1 的区别
- 方法 1 是 “先找到数据 → 修改 → 保存” ,适合改 单条数据 ,还能在修改前做额外操作(比如打印、校验)。
- 方法 2 是 “直接批量改” ,适合改 多条数据 ,代码更简洁,但要注意过滤条件(否则会改全部)~
总结(小剧场对比)
方法 1 小剧场
你:管家!把 ID=5 的小泥人拿出来~
管家:好的!(get(id=5)
)
你:给它换件新衣服 text="7777"
~
你:检查一下(print
),没问题!放回展示柜(save
)~
方法 2 小剧场
你:管家!把所有小泥人的衣服都换成 text="888"
~
管家:收到!批量操作完成(update
)~
两种方法都能修改数据,根据场景选就行啦~ 方法 1 适合改单条、需要校验的场景;方法 2 适合批量改、追求简洁的场景~ 🚀
(注意:方法 2 如果不加 filter
,会修改 所有数据 ,用的时候要小心哦!)
三、🕵️♀️ Django ORM 查询魔法
核心目标
教你用 Django ORM 从数据库里 “捞数据” !不管是找单条、多条,还是带条件筛选,都能轻松拿捏~
“捞数据” 的基本姿势(获取对象)
1. 获取单个对象(精准定位)
obj: Feedback = Feedback.objects.get(id=5) # 获取ID=5的数据
拆解:
Feedback.objects
:模型的 “数据管家”,负责和数据库唠嗑~.get(id=5)
:管家接到指令 → 去数据库找 “ID=5” 的那条数据 ,找到后包装成Feedback
对象给你~- 类比:你对管家说 “把展示柜里 ID=5 的小泥人拿过来”,管家精准找到递给你~
⚠️ 注意:如果 get
没找到数据,会报错 DoesNotExist
;如果找到多条,会报错 MultipleObjectsReturned
。所以适合 确定只有一条数据 的场景~
2. 获取多个数据(批量捞)
① 获取全部数据
obj_list: list[Feedback] = Feedback.objects.all() # 获取全部数据
.all()
:管家接到指令 → 把数据库里 所有 Feedback 数据 都捞出来,包装成列表给你~- 类比:你对管家说 “把展示柜里所有小泥人都拿过来”,管家抱来一整箱~
② 获取部分数据(带条件筛选)
obj_list: list[Feedback] = Feedback.objects.filter(id=5) # 获取部分数据
.filter(id=5)
:管家接到指令 → 去数据库找 “ID=5” 的所有数据(虽然 ID 一般唯一,但语法支持找多个 ),包装成列表给你~- 类比:你对管家说 “把展示柜里 ID=5 的小泥人都拿过来”(如果有多个重名 ID ,就都抱来 )~
③ 获取指定范围数据
obj_list: list[Feedback] = Feedback.objects.all()[:100] # 获取指定范围数据
.all()[:100]
:先捞全部数据,再 切片取前 100 条 ~- 类比:你对管家说 “把展示柜里的小泥人都拿过来,我只看前 100 个”,管家抱来一箱,你自己挑前 100 个~
条件查询(精准筛选的魔法语法)
Django ORM 提供了超方便的 条件查询语法 ,用 __
(双下划线)实现各种筛选!
条件 | 语法 | 例子(找 quality 字段) | 含义 |
---|---|---|---|
等于 | = | filter(quality=5) | quality 等于 5 |
大于 | __gt | filter(quality__gt=3) | quality 大于 3 |
大于等于 | __gte | filter(quality__gte=3) | quality 大于等于 3 |
小于 | __lt | filter(quality__lt=3) | quality 小于 3 |
小于等于 | __lte | filter(quality__lte=3) | quality 小于等于 3 |
包含(在列表里) | __in | filter(quality__in=[1,3,5]) | quality 是 1、3、5 中的一个 |
不等于 | exclude | exclude(quality=5) | quality 不等于 5 |
举个栗子🌰
比如想找 “quality 大于 3” 的数据:
obj_list = Feedback.objects.filter(quality__gt=3)
- 管家接到指令 → 去数据库找
quality
字段大于 3 的所有数据,返回列表~ - 类比:你对管家说 “把展示柜里,商品质量评分大于 3 分的小泥人拿过来”,管家精准筛选后抱来~
再举个栗子🌰
想找 “quality 不等于 5” 的数据:
obj_list = Feedback.objects.exclude(quality=5)
exclude
是管家的 “反向筛选魔法”:排除符合条件的数据~- 类比:你对管家说 “把展示柜里,商品质量评分不等于 5 分的小泥人拿过来”,管家会过滤掉评分 5 分的,抱来剩下的~
总结(小剧场)
获取单个数据
你:管家!把 ID=5 的小泥人拿过来~
管家:好的!(get(id=5)
)精准找到,递给你~
获取全部数据
你:管家!把所有小泥人都拿过来~
管家:好的!(all()
)抱来一整箱~
条件筛选数据
你:管家!把商品质量评分大于 3 分的小泥人拿过来~
管家:好的!(filter(quality__gt=3)
)筛选后抱来~
四、🗑️ Django ORM 删除数据
核心目标
教你用 Django ORM 从数据库里 “删除数据” !就像给数据库 “扔垃圾”,把不要的数据清理掉~
方法 1:实例对象删除(精准删单条)
# 1. 获取要删的数据
obj: Feedback = Feedback.objects.get(id=5) # 获取ID=5的数据
print(f"{obj=}, {obj.text}")# 2. (可选)修改数据(这里只是示例,删之前也能改)
obj.text = "7777"# 3. 删除数据
obj.delete() # 删除
1. obj = Feedback.objects.get(id=5)
→ 找到要删的数据
- 管家帮你找到 “ID=5” 的那条数据 ,赋值给
obj
~ - 类比:你对管家说 “把展示柜里 ID=5 的小泥人拿出来,我要扔了它”,管家找到后递给你~
2. obj.text = "7777"
→ (可选)删之前修改
- 删数据前,也可以改数据(虽然改了又删有点多余,只是演示~)
- 类比:拿到小泥人后,给它换件新衣服(改数据),但最后还是要扔~
3. obj.delete()
→ 把数据 “扔垃圾桶”
- 调用
delete()
,Django 会把obj
对应的数据从数据库里 永久删除 ! - 类比:你对管家说 “把这个小泥人扔垃圾桶”,管家就把它从展示柜移除~
方法 2:类方法删除(批量删)
Feedback.objects.filter(text="888").delete()
1. Feedback.objects.filter(text="888")
→ 找到要删的批量数据
- 管家先找到 所有 text 字段是
"888"
的数据 ,组成一个 “待删列表”~ - 类比:你对管家说 “把展示柜里所有衣服是
text="888"
样式的小泥人找出来,我要扔了它们”,管家找到一堆小泥人~
2. .delete()
→ 批量扔垃圾桶
- 对 “待删列表” 调用
delete()
,Django 会把这些数据 全部永久删除 ! - 类比:管家把找到的小泥人,一起扔进垃圾桶~
3. 和方法 1 的区别
- 方法 1 是 “先找到单条数据 → 删” ,适合删 单条数据 。
- 方法 2 是 “先筛选批量数据 → 删” ,适合删 多条数据 ,代码更简洁~
总结(小剧场对比)
方法 1 小剧场
你:管家!把 ID=5 的小泥人拿过来,我要扔了它~
管家:好的!(get(id=5)
)找到递给你~
你:(可选:给它换件衣服)然后说 “扔了它!”(delete()
)
管家:把小泥人从展示柜移除~
方法 2 小剧场
你:管家!把所有衣服是 text="888"
的小泥人找出来,全部扔了~
管家:好的!(filter(text="888")
)找到一堆小泥人,然后 delete()
全部扔垃圾桶~
两种方法都能删数据,根据场景选就行啦~ 方法 1 适合删单条,方法 2 适合批量删!
⚠️ 注意:删除数据是 永久操作 ,删了就找不回来啦!一定要谨慎使用~ 🚮
(记得结合条件 filter
精准删数据,别不小心删错啦~)
五、🧙♂️ Django ORM 底层 SQL 魔法!“代码→SQL” 的秘密
核心目标
Django ORM 帮我们写代码时,底层其实是转换成 SQL 语句 和数据库交互的!这节课教你:
- 看 ORM 代码对应的 SQL 长啥样~
- 直接写 SQL 和数据库交互(偶尔 ORM 搞不定时用)~
显示 SQL(看 ORM 背后的魔法咒语)
# 1. 用 ORM 写查询
obj_list: list[Feedback] = Feedback.objects.filter(id=5).filter(anonymous=False)# 2. 打印底层 SQL
print(f"sql={obj_list.query}")
obj_list
是个列表,里面装的都是 Feedback
数据对象~
1. Feedback.objects.filter(...)
→ 写 ORM 查询
- 你用 ORM 写了一个查询:找
id=5
且anonymous=False
的数据~ - 类比:你对管家说 “找 ID=5、且没匿名的小泥人”,管家听懂了你的需求~
2. obj_list.query
→ 看管家背后的 “SQL 咒语”
query
是 ORM 查询对象的一个属性,存储了 Django 转换成的 SQL 语句 !- 打印它,就能看到:Django 到底帮你生成了什么样的 SQL 去查数据库~
- 类比:你好奇管家怎么和数据库 “沟通”,于是让管家把 “沟通咒语”(SQL)给你看~
3. 打印效果
SELECT "beifan_feedback"."id", "beifan_feedback"."quality", ...
FROM "beifan_feedback"
WHERE ("beifan_feedback"."id" = 5 AND "beifan_feedback"."anonymous" = False)
- 这就是 ORM 转换成的 SQL 语句,数据库会执行它来捞数据~
- 类比:管家把你的需求,翻译成数据库能听懂的 “咒语”(SQL),然后执行!
执行 SQL(直接和数据库唠嗑)
from django.db import connectiondef my_sql():with connection.cursor() as cursor:# 1. 写 SQL 语句cursor.execute("""SELECT *, _ROWID_ "NAVICAT_ROWID" FROM "beifan_feedback" LIMIT 0, 1000""")# 2. 获取结果row = cursor.fetchone()return row
1. from django.db import connection
→ 连接数据库
connection
是 Django 帮我们管理的 数据库连接对象 ,负责和数据库建立连接~- 类比:你让管家找一个 “能直接和数据库唠嗑的电话”(
connection
),用来打电话下指令~
2. with connection.cursor() as cursor
→ 拿 “说话的话筒”
cursor
是 “数据库话筒”,用它执行 SQL 语句、获取结果~- 类比:管家拿起 “话筒”(
cursor
),准备帮你和数据库唠嗑~
3. cursor.execute(...)
→ 说 SQL 咒语
- 你直接写 SQL 语句,让
cursor
执行~ - 这里的 SQL 是:
SELECT * FROM beifan_feedback LIMIT 0, 1000
(查beifan_feedback
表,取前 1000 条 ) - 类比:你对着话筒(
cursor
)直接说 SQL 咒语,让数据库执行~
4. cursor.fetchone()
→ 听数据库的回复
- 执行 SQL 后,用
fetchone()
获取 第一条结果 (也可以用fetchall()
拿全部 )~ - 类比:你让管家听数据库的回复,然后把结果拿给你~
5. 什么时候用这种方式?
- 当 ORM 搞不定复杂查询时(比如超级复杂的多表关联、自定义函数),可以直接写 SQL ~
- 但要注意:直接写 SQL 会失去 ORM 的 “跨数据库兼容” 优势(不同数据库 SQL 语法可能不同)~
总结(小剧场对比)
显示 SQL 小剧场
你:管家!我用 ORM 写了个查询,想看看你背后对数据库说了啥咒语~
管家:好的!(obj_list.query
)把 ORM 转成的 SQL 给你看~
执行 SQL 小剧场
你:管家!我要直接和数据库唠嗑,说一段 SQL 咒语~
管家:好的!(connection
+ cursor
)帮你拿话筒、执行 SQL、拿结果~
两种方式各有用途:
- 显示 SQL :调试时看 ORM 有没有按你的想法生成 SQL ,像 “查管家的小秘密”~
- 执行 SQL :ORM 搞不定时,直接写 SQL 硬刚,像 “和数据库直接唠嗑”~
掌握这些,你就能看透 ORM 底层的魔法,还能手动控制 SQL 啦! 🎉