Django ORMのupdate入門
データを更新する方法
Django ORMでデータベースのレコードを更新する方法を解説します。save()による単一更新からupdate()による一括更新まで紹介します。
こんな人向けの記事です
- Django ORMでデータの更新方法を学びたい人
- save()とupdate()の違いを理解したい人
- 一括更新やF式を活用したい人
Step 1save()で1件更新
モデルインスタンスのフィールドを変更してsave()を呼ぶと、データベースが更新されます。
Python
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.IntegerField()
stock = models.IntegerField(default=0)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.namePython
# 1件取得してフィールドを変更し、保存
product = Product.objects.get(id=1)
print(f"変更前: {product.price}円")
product.price = 1500
product.save()
print(f"変更後: {product.price}円")実行結果
変更前: 1000円
変更後: 1500円Python
# update_fieldsで更新するフィールドを限定(パフォーマンス向上)
product = Product.objects.get(id=1)
product.price = 2000
product.save(update_fields=["price"]) # priceだけUPDATEされるupdate_fieldsを指定するメリット
save()はデフォルトで全フィールドをUPDATEします。update_fieldsを指定すると、指定したフィールドのみがUPDATE文に含まれるため、パフォーマンスが向上し、競合も防げます。Step 2update()で一括更新
QuerySetのupdate()メソッドを使うと、条件に一致する複数のレコードを1回のSQLで一括更新できます。
Python
# 在庫が0の商品を非アクティブにする
updated_count = Product.objects.filter(stock=0).update(is_active=False)
print(f"{updated_count}件の商品を非アクティブにしました")
# 全商品の価格を1000円にする
Product.objects.all().update(price=1000)
# 特定条件の複数フィールドを同時に更新
Product.objects.filter(
is_active=False
).update(
price=0,
stock=0
)実行結果
3件の商品を非アクティブにしましたupdate()の注意点
update()はSQLを直接発行するため、モデルのsave()メソッドやシグナル(pre_save, post_save)は呼ばれません。これらの処理が必要な場合はsave()を使ってください。Step 3F式を使った相対更新
現在の値を基準に更新したい場合は、F()式を使います。Pythonにデータを読み込まずにデータベース上で計算できます。
Python
from django.db.models import F
# 全商品の価格を10%値上げ
Product.objects.all().update(price=F("price") * 1.1)
# 在庫を1つ減らす
Product.objects.filter(id=1).update(stock=F("stock") - 1)
# 複数フィールドを相対的に更新
Product.objects.filter(is_active=True).update(
price=F("price") + 100,
stock=F("stock") + 10
)
# save()でもF式は使える
product = Product.objects.get(id=1)
product.stock = F("stock") + 5
product.save(update_fields=["stock"])
# 注意: F式を使った後はrefresh_from_db()が必要
product.refresh_from_db()
print(f"在庫: {product.stock}")F式のメリット
F式を使うと、データベース側で計算が行われるため、複数のリクエストが同時にデータを更新する場合でも競合(レースコンディション)を防ぐことができます。Step 4update_or_create()で更新または作成
条件に一致するデータがあれば更新し、なければ新規作成する場合はupdate_or_create()を使います。
Python
# nameが"りんご"のデータがあれば更新、なければ作成
product, created = Product.objects.update_or_create(
name="りんご", # 検索条件
defaults={"price": 200, "stock": 50} # 更新/作成するフィールド
)
if created:
print(f"新規作成: {product.name}")
else:
print(f"更新: {product.name} → {product.price}円")
# 複数の検索条件も指定可能
product, created = Product.objects.update_or_create(
name="りんご",
is_active=True,
defaults={"price": 250}
)実行結果
更新: りんご → 200円Step 5save()とupdate()の使い分け
状況に応じて適切な更新方法を選びましょう。
Python
# === save(): モデルの振る舞いが必要なとき ===
# ✓ save()メソッドをオーバーライドしている場合
# ✓ pre_save / post_saveシグナルが必要な場合
# ✓ バリデーションを実行したい場合
product = Product.objects.get(id=1)
product.price = 2000
product.full_clean() # バリデーション実行
product.save()
# === update(): 高速な一括更新 ===
# ✓ 大量のレコードを更新する場合
# ✓ シグナルやバリデーションが不要な場合
# ✓ パフォーマンスを重視する場合
Product.objects.filter(is_active=False).update(stock=0)
# === bulk_update(): save()の動作で複数件更新 ===
products = list(Product.objects.filter(is_active=True))
for p in products:
p.price = int(p.price * 1.1)
Product.objects.bulk_update(products, ["price"])
# bulk_update()はSQLをまとめるが、シグナルは呼ばれないまとめ
save()はインスタンスを変更後に保存する基本的な更新方法update()はQuerySetで条件を指定して一括更新できる(高速)F()式を使うとデータベース上で相対的な値の更新ができるupdate_or_create()で「あれば更新、なければ作成」が1行で書けるupdate()はsave()やシグナルを呼ばないため、用途に応じて使い分ける