__(ダブルアンダースコア)とは?

Djangoにおいて__(ダブルアンダースコア)は、モデル間の関係フィールドを通じてデータベースクエリを作成する際に使用されます。簡単に言えば、他のテーブルに接続されたフィールドにアクセスしたり、特定の条件を持つデータをフィルタリングするために用いられます。

例えば、二つ以上のモデルがForeignKeyOneToOneFieldなどの関係で接続されている場合、その関係を通じて望むフィールドにアクセスすることができます。ここで__は一種の「接続リンク」として機能し、異なるモデルのフィールドをチェーンのように接続してアクセスする方法です。

例: モデル間の関係における__の使用

簡単な例を挙げましょう。もしProfileモデルがUserモデルと接続されており、そのユーザーモデルにはusernameというフィールドがあると仮定します。私たちはProfileモデルからUserusernameに基づいて特定のプロファイルをフィルタリングすることができます。

モデル定義:

from django.db import models
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    pass

class Profile(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    bio = models.TextField()

上記の例でProfileモデルはCustomUserと1:1の関係を結んでいます。それでは、__を使用してProfileからCustomUserのフィールドにアクセスする方法を見ていきましょう。

__を使用したクエリ:

# CustomUserのusernameを基にProfileオブジェクトをフィルタリング
profiles = Profile.objects.filter(user__username='jesse')

ここでuser__usernameが重要です。userProfileモデルのCustomUserと接続されたフィールドで、そのフィールドのusernameにアクセスするために__で接続します。こうすることでProfileモデルからCustomUserusernameフィールドを基にデータを取得することができます。

__の多様な活用

__は単にフィールドアクセスだけでなく、条件を付けるのにもよく使われます。Djangoはクエリセットで様々な条件を設定できる多くのフィルタリング機能を提供しており、そのほとんどが__を通じて実装されています。よく使用される条件は以下の通りです:

  • exact: 正確に一致する値を探します。(デフォルトのため省略可能)
  • icontains: 大文字小文字を区別せずに含まれる値を探します。
  • gt, lt, gte, lte: 大きいまたは小さい値を探す条件 (greater than, less than).
  • startswith, endswith: 特定の文字列で始まるまたは終わる値を探します。

例: 多様なフィルター条件

# CustomUserのメールが'gmail.com'を含むすべてのプロファイルを取得
profiles_with_gmail = Profile.objects.filter(user__email__icontains='gmail.com')

# CustomUserのIDが10より大きいプロファイルを取得
profiles_with_id_gt_10 = Profile.objects.filter(user__id__gt=10)

# CustomUserのusernameが'jesse'で始まるプロファイルを取得
profiles_starting_with_jesse = Profile.objects.filter(user__username__startswith='jesse')

__を通じた多重関係フィールドアクセス

Djangoにおける最も強力な機能の一つは、複数のモデルが接続されている場合でも__を通じて多重関係に沿ってデータを取得できる点です。例えば、OrderモデルがProfileと接続され、再びProfileCustomUserと接続されている状況を考えてみましょう。

多重関係モデルの例:

class Order(models.Model):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    order_date = models.DateTimeField()
    amount = models.DecimalField(max_digits=10, decimal_places=2)

今、私たちはOrderからCustomUserusernameを基にデータを取得したいと仮定します。

多重関係フィルタリング:

# OrderからCustomUserのusernameが'jesse'の注文を取得
orders_for_user = Order.objects.filter(profile__user__username='jesse')

ここでprofile__user__usernameで多くの段階の関係をたどり、CustomUserのフィールドにアクセスできます。OrderProfileCustomUserと続く関係を__でつないで簡単にフィルタリングを実現しています。

まとめ

  • __はモデル間の関係をたどる際にフィールドを参照するために使用されます。
  • 多様なクエリ条件を設定してデータをフィルタリングすることができます。
  • 多重関係のフィールドを接続することで複雑なクエリも簡単に処理できます。

これで__の役割と使い方を理解したので、Django ORMでより強力なクエリを作成できるようになります。データベースの関係構造を考えながらこの記号を適切に活用すれば、効率的なデータ処理と複雑な関係を簡単に扱えるようになるでしょう。