Django 中的資料庫update() 和 save() 方法的機制的不同

EricS9999發表於2024-12-10

1. save() 方法

機制

呼叫 save() 方法時,會先對模型例項的欄位進行驗證(如欄位型別、長度約束等)。

如果模型定義了 clean() 或者欄位設定了驗證規則(如 validators),這些規則也會被執行。

驗證透過後,Django 才會將資料儲存到資料庫中。

觸發的邏輯

觸發模型的 pre_save 和 post_save 訊號。

執行模型的 full_clean() 方法,對資料完整性進行檢查。

適用場景

儲存或更新單個物件時,確保資料完整性和驗證邏輯得以執行。

示例

1 # 假設模型如下:
2 class Employee(models.Model):
3     name = models.CharField(max_length=50)
4     salary = models.PositiveIntegerField()
5 
6 # 建立或更新例項
7 emp = Employee.objects.get(id=1)
8 emp.salary = -100  # 負數會違反 PositiveIntegerField 的規則
9 emp.save()  # 丟擲 ValidationError

2. update() 方法

機制

update() 是基於查詢集(QuerySet)的批次操作方法,直接生成 SQL UPDATE 語句並執行,不載入模型例項,也不執行欄位驗證。

不會觸發模型的 clean() 方法或任何訊號(如 pre_save 和 post_save)。

操作是資料庫層面的直接更新。

適用場景

批次更新多個物件時,用於提高效率,因為不會載入模型例項或執行驗證。

示例

1 # 批次更新
2 Employee.objects.filter(salary__lt=3000).update(salary=3500)
3 
4 # 單個更新(仍然是批次更新語法)
5 Employee.objects.filter(id=1).update(salary=-100)  # 不會丟擲驗證錯誤,直接寫入資料庫

3. 主要區別

特性

save() update()
欄位驗證 會進行欄位驗證,觸發 full_clean() 不進行欄位驗證,直接生成 SQL 語句
訊號觸發 觸發 pre_save 和 post_save 訊號 不觸發任何訊號
操作範圍 僅限單個例項 支援批次操作,可更新多個記錄
效能 較低,需載入例項並逐一儲存 較高,直接生成 SQL 並批次執行
用途 確保資料驗證和完整性 快速批次更新,無需模型例項

4. 使用建議

1. 使用 save()

對單個例項進行更新或插入,並希望確保資料驗證邏輯得以執行。

例如,在使用者提交表單後儲存物件時。

2. 使用 update()

在不需要欄位驗證和訊號觸發的情況下,進行批次更新操作以提升效能。

例如,批次修改某些狀態欄位時。

相關文章