DjangoのORMで、データベース上のフィールドの値を直接参照して演算を行うには、F式(Fオブジェクト)を使用します。Pythonにデータを読み込まずにデータベース側で計算を完結させるため、効率的な処理が可能です。
基本的な使い方
views.py
update_model = Sales.objects.update(sale = F('sale')*1.1)
説明
Step 1F式の基本
Djangoでは、F式を使用してデータベースレベルでフィールド値に対する計算を行うことができます。基本的な構文は以下の通りです:
from django.db.models import F
F('フィールド名')計算式
このF式を使用すると、Pythonレベルではなくデータベースレベルでの操作が可能になり、効率的なデータ更新ができます。
Step 2基本的な使用例
例えば、Salesモデルのsaleフィールドの値を1.1倍(10%増)する場合:
from django.db.models import F
# Salesモデルのsaleフィールドを全て1.1倍する
Sales.objects.update(sale=F('sale') * 1.1)
上の例は、Salesモデルのsaleフィールドを全て1.1倍した値にして更新しています。
Step 3様々な計算例
F式では様々な計算が可能です:
# 加算
Product.objects.update(price=F('price') + 100) # 価格を100円上げる
# 減算
Product.objects.update(price=F('price') - 50) # 価格を50円下げる
# 乗算
Product.objects.update(price=F('price') * 1.05) # 価格を5%上げる
# 除算
Product.objects.update(price=F('price') / 2) # 価格を半額にする
# べき乗
Product.objects.update(price=F('price') ** 2) # 価格を2乗する
Step 4条件付き更新
特定の条件に一致するレコードだけを更新することもできます:
# 価格が1000円以上の商品のみ10%割引
Product.objects.filter(price__gte=1000).update(price=F('price') * 0.9)
# 在庫が10個未満の商品の在庫を2倍にする
Product.objects.filter(stock__lt=10).update(stock=F('stock') * 2)
Step 5複数フィールドの計算
F式を使って別のフィールドを参照した計算も可能です:
# 単価と数量から合計金額を計算
Order.objects.update(total_amount=F('unit_price') * F('quantity'))
# 在庫と予約数から利用可能数を計算
Product.objects.update(available=F('stock') - F('reserved'))
Step 6実践的な使用例
views.pyでのF式の使用例:
from django.shortcuts import redirect
from django.contrib import messages
from django.db.models import F
from .models import Product
def apply_discount(request):
# 割引率を取得(デフォルトは10%)
discount_rate = float(request.POST.get('discount_rate', 10)) / 100
category_id = request.POST.get('category_id')
# 基本クエリ
query = Product.objects
# カテゴリが指定されている場合はフィルタリング
if category_id:
query = query.filter(category_id=category_id)
# 価格を割引率に基づいて更新
updated_count = query.update(price=F('price') * (1 - discount_rate))
messages.success(request, f"{updated_count}件の商品に{int(discount_rate*100)}%の割引を適用しました")
return redirect('product_list')
def increment_view_count(request, product_id):
# 商品の閲覧数を1増やす
Product.objects.filter(id=product_id).update(view_count=F('view_count') + 1)
# 商品詳細ページにリダイレクト
return redirect('product_detail', product_id=product_id)
F式のメリット:
- データベースレベルで計算が行われるため、Python側でデータを取得して計算するよりも効率的です。
- 複数のユーザーが同時に更新した場合でも、競合状態(race condition)を回避できます。
- 大量のレコードを一度に更新する場合、メモリ使用量が少なくて済みます。
まとめ
- F式を使うとデータベース側でフィールドの値を直接参照・演算できる
update()と組み合わせて、値の増減などをSQL1文で実行できる- レースコンディション(競合状態)を防ぐ効果がある
filter()内でフィールド同士の比較に使用できるannotate()内で計算フィールドを追加する際にも活用できるfrom django.db.models import Fでインポートして使用する