Django update_or_create() 用法詳解
更新日期: 2025 年 2 月 24 日
本文為 資料庫正規化 基本介紹系列文,第 1 篇:
在 Django 的 ORM(Object-Relational Mapping,物件關聯對映)中,update_or_create()
是一個 便捷的方法,它可以用來 更新現有記錄,或在記錄不存在時自動建立新記錄。
這在處理資料時非常實用,尤其是在 批量匯入資料、同步外部 API 數據,或 確保唯一記錄存在 時,能夠有效減少程式碼複雜度。
在這篇文章中,我們將詳細介紹 update_or_create()
的用法,包括其 基本語法、參數說明、實際範例,並比較它與其他 ORM 方法的異同,讓你能夠靈活運用這個強大的方法!
update_or_create()
是什麼?
在 Django ORM 中,update_or_create()
提供了一種 先查找再更新,若不存在則建立 的機制,語法如下:
Model.objects.update_or_create(defaults=None, **kwargs)
參數說明
參數 | 說明 |
---|---|
defaults | (選填) 這是一個字典,包含要 更新或設定 的欄位值。 |
**kwargs | (必要) 這是查找條件,用來 篩選對應的資料記錄。如果找不到,就會建立新的記錄。 |
回傳值
update_or_create()
會回傳一個 (物件, created) 的 tuple:
物件
:更新或建立的 Django Model 物件。created
(布林值):如果是新建立的物件,則回傳True
,否則回傳False
(代表該記錄已存在,並已更新)。
基本範例
假設我們有一個 UserProfile
模型
from django.db import models
class UserProfile(models.Model):
username = models.CharField(max_length=100, unique=True)
email = models.EmailField(unique=True)
age = models.IntegerField(default=18)
def __str__(self):
return self.username
使用 update_or_create()
from myapp.models import UserProfile
user, created = UserProfile.objects.update_or_create(
username="john_doe", # 查找條件
defaults={"email": "[email protected]", "age": 25} # 如果存在就更新
)
if created:
print("新用戶已建立:", user)
else:
print("用戶已存在,已更新資料:", user)
可能的情境
- 如果
username="john_doe"
已經存在:email
會被更新為"[email protected]"
。age
會被更新為25
。created
會是False
,表示這筆資料已經存在,並且已被更新。
- 如果
username="john_doe"
不存在:- 會建立一筆新的
UserProfile
記錄。 created
會是True
,表示這是一筆新資料。
- 會建立一筆新的
update_or_create()
與 get_or_create()
的比較
update_or_create()
與 get_or_create()
類似,主要區別如下:
方法 | 功能 |
---|---|
get_or_create() | 如果找到資料就回傳,如果沒找到就建立新資料,不會更新現有資料。 |
update_or_create() | 如果找到資料就更新,如果沒找到就建立新資料。 |
get_or_create()
範例
user, created = UserProfile.objects.get_or_create(
username="john_doe",
defaults={"email": "[email protected]", "age": 25}
)
- 如果
john_doe
存在,它不會更新email
或age
,只會返回現有物件。 - 如果
john_doe
不存在,就會建立新的記錄。
👉 如果你需要更新現有資料,請使用 update_or_create()
。
update_or_create()
的進階應用
使用多個查找條件
你可以使用多個條件來查找記錄:
user, created = UserProfile.objects.update_or_create(
username="john_doe",
email="[email protected]",
defaults={"age": 30} # 只更新 `age` 欄位
)
這裡的查找條件是 username="john_doe"
且 email="[email protected]"
。
只更新部分欄位
如果只想更新某些欄位,可以在 defaults
內傳入所需的欄位:
user, created = UserProfile.objects.update_or_create(
username="jane_doe",
defaults={"age": 28} # 只更新 `age`,不影響其他欄位
)
update_or_create()
內建 save()
update_or_create()
會在內部執行 save()
,所以不需要額外呼叫:
user, created = UserProfile.objects.update_or_create(
username="michael",
defaults={"email": "[email protected]"}
)
print(user.email) # 自動更新後的資料
這與手動執行 .save()
效果相同。
與 transaction.atomic()
搭配使用
在某些情況下,若有多個 update_or_create()
可能影響到相同的記錄,建議使用 資料庫交易(transaction)來確保資料一致性:
from django.db import transaction
with transaction.atomic():
user, created = UserProfile.objects.update_or_create(
username="alice",
defaults={"email": "[email protected]", "age": 22}
)
這樣可以確保 在多個請求同時寫入資料時,不會產生競爭條件(Race Condition)。
什麼時候該使用 update_or_create()
?
適用情境:
✅ 匯入外部資料(例如 API 回應數據,若存在就更新,否則建立)。
✅ 批量同步資料(避免重複建立相同記錄)。
✅ 確保唯一記錄存在(例如每個 username
只能有一筆記錄)。
✅ 避免手動查找與更新(相比 get()
+ save()
,更簡潔高效)。
不適用情境:
❌ 不需要更新資料,只要確保記錄存在時,應該用 get_or_create()
。
❌ 批量更新大量資料,用 bulk_update()
可能效能更好。
總結
✅ update_or_create()
先查找,若存在則更新,若不存在則建立新記錄。
✅ 回傳 (物件, created)
,created=True
代表新建立,False
代表已更新。
✅ 可用 defaults={}
指定要更新的欄位,不影響 kwargs
查找條件內的欄位。
✅ 比 get_or_create()
更適合需要「更新」的情境。
✅ 可與 transaction.atomic()
搭配,確保數據一致性。
💡 掌握 update_or_create()
,讓你的 Django 專案更高效、靈活!🚀