ORM

Django ORMで固定値をフィールドに追加|annotateとValueの使い方

DjangoのORMで、QuerySetの各レコードに固定値や計算結果を新しいフィールドとして追加するには、annotate()Value()を組み合わせます。条件に応じた値の代入など、実践的なパターンを解説します。

基本的な使い方

views.py
from django.db.models import Value

model = Person.objects.all().annotate(
    test = Value(1)
).values()

print(model)

説明

\n

1Valueオブジェクトの基本

\n

Djangoでは、Value式を使って固定値をORMのクエリに組み込むことができます。基本的な構文は以下の通りです:

\n \n
\n
from django.db.models import Value\n\nValue(値)
\n
\n \n

ORMではannotateで作成したフィールドに直接値を代入しようとするとエラーとなるので、Valueオブジェクトを使用する必要があります。

\n\n\n\n

2基本的な使用例

\n

例えば、annotateメソッドでtestという名前のフィールドに固定値の1を代入する場合:

\n \n
\n
from django.db.models import Value\n\n# testフィールドに1を代入\npersons = Person.objects.annotate(test=Value(1))
\n
\n \n

上の例では、testフィールドに1を代入しています。

\n\n\n\n

3様々な型の値を設定

\n

Valueオブジェクトには、様々な型の値を設定することができます:

\n \n
\n
# 数値\npersons = Person.objects.annotate(score=Value(100))\n\n# 文字列\npersons = Person.objects.annotate(status=Value('アクティブ'))\n\n# 真偽値\npersons = Person.objects.annotate(is_featured=Value(True))\n\n# 日付・時刻(from djangoのみをインポートして簡潔に示す)\nfrom django import timezone\npersons = Person.objects.annotate(\n    reference_date=Value(timezone.now().date())\n)
\n
\n\n\n\n

4計算式との組み合わせ

\n

Valueオブジェクトは、F式や計算式と組み合わせて使うことができます:

\n \n
\n
from django.db.models import F, Value\n\n# 年齢に固定値を足す\npersons = Person.objects.annotate(\n    adjusted_age=F('age') + Value(5)  # 5歳上の年齢\n)\n\n# 固定の割引率を適用\nproducts = Product.objects.annotate(\n    discount_rate=Value(0.1),  # 10%割引\n    sale_price=F('price') * (Value(1) - F('discount_rate'))\n)
\n
\n\n\n\n

5文字列連結での使用

\n

Valueオブジェクトは文字列連結にも使用できます(PostgreSQL使用時):

\n \n
\n
from django.db.models import Value\nfrom django.db.models.functions import Concat\n\n# 姓名の間にスペースを挿入して連結\npersons = Person.objects.annotate(\n    full_name=Concat(\n        'first_name', \n        Value(' '),  # スペースを挿入\n        'last_name'\n    )\n)\n\n# テキストを追加\nproducts = Product.objects.annotate(\n    price_text=Concat(\n        'name',\n        Value(': '),\n        'price',\n        Value('円')\n    )\n)
\n
\n\n\n\n

6実践的な使用例

\n

views.pyでのValueオブジェクトの使用例:

\n \n
\n
from django.shortcuts import render\nfrom django.db.models import Value, F, ExpressionWrapper, DecimalField\nfrom django.db.models.functions import Concat\nfrom .models import Product\n\ndef product_list(request):\n    # 税率と割引率を定義\n    tax_rate = 0.1  # 10%\n    discount_rate = 0.05  # 5%\n    \n    # 様々な価格計算と固定値の適用\n    products = Product.objects.annotate(\n        # 固定値\n        tax_rate=Value(tax_rate),\n        discount_rate=Value(discount_rate),\n        \n        # 価格計算\n        price_with_tax=ExpressionWrapper(\n            F('price') * (Value(1) + F('tax_rate')),\n            output_field=DecimalField(max_digits=10, decimal_places=2)\n        ),\n        \n        discounted_price=ExpressionWrapper(\n            F('price') * (Value(1) - F('discount_rate')),\n            output_field=DecimalField(max_digits=10, decimal_places=2)\n        ),\n        \n        # 表示用テキスト\n        price_label=Concat(\n            'name',\n            Value(' - '),\n            'price',\n            Value('円 (税込: '),\n            F('price_with_tax'),\n            Value('円)')\n        )\n    )\n    \n    return render(request, 'products/list.html', {\n        'products': products,\n        'tax_rate': tax_rate * 100,\n        'discount_rate': discount_rate * 100\n    })
\n
\n \n

テンプレートでの使用例(list.html):

\n \n
\n
<h1>商品一覧</h1>\n<p>税率: {{ tax_rate }}% / 割引率: {{ discount_rate }}%</p>\n\n<table>\n    <tr>\n        <th>商品名</th>\n        <th>通常価格</th>\n        <th>税込価格</th>\n        <th>割引価格</th>\n    </tr>\n    {% for product in products %}\n        <tr>\n            <td>{{ product.name }}</td>\n            <td>{{ product.price }}円</td>\n            <td>{{ product.price_with_tax }}円</td>\n            <td>{{ product.discounted_price }}円</td>\n        </tr>\n    {% endfor %}\n</table>\n\n<h2>商品ラベル</h2>\n<ul>\n    {% for product in products %}\n        <li>{{ product.price_label }}</li>\n    {% endfor %}\n</ul>
\n
\n\n\n
ポイント
\n

重要ポイント:

\n
    \n
  • Valueオブジェクトは、Django ORMのクエリ内で固定値を使用するために必要です。
  • \n
  • 数値、文字列、真偽値、日付など、様々な型の値をValueオブジェクトで包むことができます。
  • \n
  • F式と組み合わせることで、既存のフィールド値と固定値を組み合わせた計算が可能です。
  • \n
  • 複雑な計算やテキスト連結を行う場合は、適切なoutput_fieldを指定することがあります。
  • \n
\n

まとめ

  • Value()で固定値をannotateに追加できる
  • output_fieldでデータ型を明示的に指定できる
  • Case/Whenと組み合わせて条件ごとに異なる値を代入できる
  • 文字列の結合にはConcat()を使用する
  • annotateで追加したフィールドは通常のフィールドと同様にアクセスできる