跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

Django怎么增删改查_ORM基础QuerySet操作详解(CRUD)

create() 一步完成实例化和数据库写入,但不触发 save() 钩子、信号及 full_clean() 校验,且要求非空字段显式传参,外键须传实例而非 ID。 怎么用
create()
新增数据,而不是先实例化再
save()
直接调用模型的
create()
是最简明的新增方式,它一步完成实例化和写入数据库,省去中间状态。但要注意:它不触发
save()
方法里的自定义逻辑(比如信号、字段预处理、
pre_save
钩子),也不校验模型层面的
full_clean()
—— 这些都得自己补。
create()
要求所有非空字段(
null=False
,
blank=False
)必须显式传参,缺一个就报
TypeError
外键字段传的是对象实例,不是 ID(比如
author=user_obj
,不是
author_id=1
) 如果字段有默认值(
default=...
或
auto_now_add=True
),
create()
会自动用上;但
default
是可调用对象时(如
default=uuid4
),每次调用仍会重新执行 批量插入别用它——单次
create()
对应一条
INSERT
,效率低;改用
bulk_create()
示例:
User.objects.create(username="alice", email="a@b.c", is_active=True)
为什么
filter().delete()
不走模型的
delete()
方法 因为
QuerySet.delete()
是底层 SQL 直删(
DELETE FROM ...
),绕过了 Python 层的模型实例生命周期。这意味着:信号(
pre_delete
/
post_delete
)会触发,但模型自己的
delete()
方法不会运行,关联的文件、缓存、自定义清理逻辑全被跳过。 想执行模型级删除逻辑?必须先
list()
或迭代取出实例,再对每个实例调
.delete()
外键设了
on_delete=models.CASCADE
的关联记录,SQL 层会自动删,但级联对象自身的
delete()
依然不执行
filter(...).delete()
返回的是一个元组
(deleted_count, {'app.Model': count})
,不是 QuerySet,不能链式操作 软删除场景(比如加
is_deleted
字段)必须手动更新,不能依赖
delete()
错误示范:
Comment.objects.filter(post_id=123).delete()
—— 如果 Comment 里有上传的图片要同步删,这里就漏了。
get()
和
filter().first()
到底该用哪个
get()
语义是“我确定有且仅有一个”,查不到或查到多个都抛异常;
filter().first()
是“拿第一个,没有就 None”,更宽容,但容易掩盖数据异常。 Python 网站开发之Django环境搭建 WORD版 本文档主要讲述的是Python 网站开发之Django环境搭建;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 主键查询、唯一字段(
unique=True
)查单条,优先用
get()
—— 它的异常(
DoesNotExist
/
MultipleObjectsReturned
)能暴露数据问题 带业务逻辑的“尝试获取”场景(比如用户登录时查 token),用
filter().first()
更安全,避免把
DoesNotExist
冒泡成 500
filter().first()
不会触发
MultipleObjectsReturned
,但它返回的可能是任意一条(无序),除非你显式加
.order_by()
性能上两者几乎没差别,都是生成
SELECT ... LIMIT 1
;但
get()
多一次结果集检查(Python 层判断数量) 常见坑:
User.objects.filter(email="x").get()
—— 如果邮箱没建唯一索引,重复注册就会崩。 更新字段时,
update()
和
save()
的实际区别在哪
update()
是纯 SQL 更新(
UPDATE ... SET ... WHERE
),不加载对象、不触发模型验证、不走字段的
pre_save
、不发
pre_save
信号;
save()
是实例级更新,走完整流程,但可能 N+1。 只改一两个字段、且不需要任何钩子时,
update()
更快更安全(比如
Post.objects.filter(id=1).update(view_count=F("view_count")+1)
)
update()
不能更新外键关联字段(如
author=new_user
),只能更新本表字段;也不能用
F()
以外的表达式(比如函数调用、Python 变量运算)
save()
会重算所有字段的
auto_now
,而
update()
不会——除非你显式写进 SQL(
update(modified_at=Now())
)
update()
返回影响行数;
save()
返回 None,且只更新当前实例已修改的字段(
update_fields
参数可限定) 典型误用:
obj.title = "new"; obj.save()
在高并发计数场景下,可能覆盖别人刚写的
view_count
—— 这时候就得换
update()
+
F()
。 ORM 的 CRUD 看似简单,真正卡住人的往往不是语法,而是哪一步绕过了信号、哪条 SQL 没走验证、哪个字段的默认行为在批量操作里失效了。多看生成的 SQL(
str(qs.query)
),比死记文档管用。

相关文章