pre_save 和 post_save 到底在 save() 的哪个位置触发?对象有没有 pk?事务提交了没有?这篇把信号和 SQL 放进同一条时间线里,一行行对照。
pre_save(pk=None, created=None, update_fields=None)
SQL: INSERT INTO "lab_item" ("name", "n") VALUES (%s, %s)
post_save(pk=1, created=True, update_fields=None)用 connection.execute_wrapper 记下每条 SQL,和信号回调排进同一个列表,才能看出真实的先后。
save(): pre_save(pk=2, created=None, update_fields=None) SQL: UPDATE "lab_item" SET "name" = %s, "n" = %s WHERE "l post_save(pk=2, created=False, update_fields=None) save(update_fields=["n"]): pre_save(pk=2, created=None, update_fields=['n']) SQL: UPDATE "lab_item" SET "n" = %s WHERE "lab_item"."id" post_save(pk=2, created=False, update_fields=['n'])
UPDATE 时 created 是 False;update_fields 为 None 表示保存了全部字段。
SQL: BEGIN
pre_save(pk=None, created=None, update_fields=None)
SQL: INSERT INTO "lab_item" ("name", "n") VALUES (%s, %s)
post_save(pk=3, created=True, update_fields=None)
(atomic 块内最后一行)post_save 在 COMMIT 之前触发,这是下一篇要展开的问题:receiver 里做的事看到的是「未提交」的数据。
instance.delete():
SQL: BEGIN
pre_delete(pk=4, created=None, update_fields=None)
SQL: DELETE FROM "lab_item" WHERE "lab_item"."id" IN (%s)
post_delete(pk=4, created=None, update_fields=None)
queryset.update(n=1): ['SQL: UPDATE "lab_item" SET "n" = %s WHERE "lab_item"."nam']
get_or_create(不存在):
SQL: SELECT "lab_item"."id", "lab_item"."name", "lab_item
SQL: BEGIN
pre_save(pk=None, created=None, update_fields=None)
SQL: INSERT INTO "lab_item" ("name", "n") VALUES (%s, %s)
post_save(pk=6, created=True, update_fields=None)批量的 queryset.update() 不走 save(),不发信号;bulk_create 等见第 110 篇。
pre_save 里把 name 改成大写 → 库里: LOWER post_save 里改 instance.name → 内存里: changed-after 库里: orig
如果要在保存前修改字段,放在 pre_save(或者 save() / clean());在 post_save 里改 instance 不会自动写回。