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