Django update_or_create() 用法詳解

更新日期: 2025 年 2 月 24 日

在 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)

可能的情境

  1. 如果 username="john_doe" 已經存在
    • email 會被更新為 "[email protected]"
    • age 會被更新為 25
    • created 會是 False,表示這筆資料已經存在,並且已被更新。
  2. 如果 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 存在,它不會更新 emailage,只會返回現有物件。
  • 如果 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 專案更高效、靈活!🚀

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *