ルックアップ API リファレンス¶
このドキュメントには、データベースクエリの WHERE 句を構築するための Django API であるルックアップの API リファレンスがあります。ルックアップの 使い方 については クエリを作成する を、新しいルックアップの 作り方 については カスタムのルックアップを書く を参照してください。
ルックアップAPIには2つのコンポーネントがあります。ルックアップを登録する RegisterLookupMixin クラスと、ルックアップとして登録するためにクラスが実装しなければならないメソッドのセットである クエリ式 API です。
Django には、クエリ式 API に従う 2 つの基本クラスがあり、すべての Django 組み込みルックアップはここから派生しています:
ルックアップ式は3つの部分で構成されています:
フィールド部分(例:
Book.objects.filter(author__best_friends__first_name...);トランスフォーム(変換)部分(省略可) (
lower__first3chars__reversedなど);ルックアップ部分 (
__icontainsなど)。省略した場合のデフォルトは__exactです。
登録API¶
Django は RegisterLookupMixin を使って、自分自身やそのインスタンスにルックアップを登録するインターフェイスをクラスに与えます。代表的な例は Field で、これはすべてのモデルフィールドの基底クラスです。 Transform もその一つで、これはすべての Django トランスフォームの基底クラスです。
- class lookups.RegisterLookupMixin¶
クラスのルックアップ API を実装するミックスインです。
- classmethod register_lookup(lookup, lookup_name=None)¶
クラスまたはクラスのインスタンスに新しいルックアップを登録します。たとえば、次のようにします:
DateField.register_lookup(YearExact) User._meta.get_field("date_joined").register_lookup(MonthExact)
このコードは
DateFieldのYearExactルックアップとUser.date_joinedのMonthExactルックアップを登録します( フィールドアクセス API を使用して単一のフィールドインスタンスを取得できます)。このルックアップは既に存在する同じ名前のルックアップを上書きします。フィールドインスタンスに登録されたルックアップはクラスに登録されたルックアップよりも優先されます。lookup.lookup_nameが指定された場合はlookup_nameが使用され、指定されなかった場合はlookup.lookup_nameが使用されます。
クラスがルックアップであるためには、 クエリ式 API に従わなければなりません。 Lookup と Transform は当然この API に従います。
クエリ式 API¶
クエリ式 API はクラスがクエリ式で使用できるように定義するメソッドの共通セットで、クラス自身を SQL 式に変換します。フィールドの直接参照、集計(Aggregation)、 Transform はこのAPIに従う例です。あるクラスが以下のメソッドを実装している場合、そのクラスはクエリ式APIに従っていると言えます:
- as_sql(compiler, connection)¶
式の SQL フラグメントを生成します。タプル
(sql, params)を返します。sqlは SQL 文字列で、paramsはクエリパラメータのリストまたはタプルです。compilerはSQLCompilerオブジェクトで、他の式をコンパイルするためのcompile()メソッドを持っています。connectionはクエリの実行に使用する接続です。expression.as_sql()の呼び出しは通常正しくありません。 代わりにcompiler.compile(expression)を使用する必要があります。compiler.compile()メソッドは式のベンダ固有のメソッドの呼び出しを行います。as_vendorname()メソッドやサブクラスがSQL文字列の生成を上書きするためにデータを提供する必要がありそうな場合は、このメソッドにカスタムキーワード引数を定義できます。たとえば、Func.as_sql()を参照してください。
- as_vendorname(compiler, connection)¶
as_sql()メソッドと同じように動作します。式がcompiler.compile()によってコンパイルされると、Django はまずas_vendorname()を呼び出そうとします。ここでvendornameはクエリを実行するバックエンドのベンダ名です。vendornameは Django の組み込みバックエンドではpostgresql、oracle、sqlite、mysqlのいずれかです。
- get_lookup(lookup_name)¶
ルックアップ名
lookup_nameを返さなければなりません。インスタンスンスではself.output_field.get_lookup(lookup_name)を返します。
- get_transform(transform_name)¶
ルックアップ名
transform_nameを返さなければなりません。インスタンスンスではself.output_field.get_transform(transform_name)を返します。
Transform リファレンス¶
- class Transform[ソース]¶
Transformはフィールドの変換を実装するための汎用クラスです。主な例はDateFieldをIntegerFieldに変換する__yearです。ルックアップ式で
Transformを使用する場合の表記は<expression>__<transformation>(例date__year) です。このクラスは クエリ式 API に従っており、
<expression>__<transform1>__<transform2>を使用できます。これは Func() 式 に特化したもので、引数を一つだけ受け取ることができます。 また、フィルタの右辺やアノテーションとして直接使用することもできます。- bilateral¶
このトランスフォームを
lhsとrhsの両方に適用するかどうかを示すブール値です。両者の変換はrhsに対して、ルックアップ式に現れる順番で適用されます。デフォルトではFalseに設定されています。たとえば、 カスタムのルックアップを書く を参照してください。
- lookup_name¶
クエリ式のパース時に使用するルックアップ名です。文字列
"__"を含むことはできません。
Lookup リファレンス¶
- class Lookup[ソース]¶
ルックアップ
Lookupはルックアップを実装するための汎用クラスです。ルックアップは左辺lhs; 右辺rhs;lookup_nameを持つクエリ式で、lhs in rhsやlhs > rhsのようにlhsとrhsをブール値で比較します。式の中でルックアップを使用するための主な記法は
<lhs>__<lookup_name>=<rhs>です。ルックアップは下記のようにQuerySetフィルタの中で直接使うこともできます:Book.objects.filter(LessThan(F("word_count"), 7500))
...下記のように、アノテーションでも使用できます:
Book.objects.annotate(is_short_story=LessThan(F("word_count"), 7500))
- rhs¶
右辺 -
lhsと比較されるもの。これは単なる値であったり、SQL にコンパイルされるものであったり、一般的にはF()オブジェクトやQuerySetであったりします。
- lookup_name¶
このルックアップの名前で、クエリ式をパースする際に識別するために使用します。文字列
"__"を含むことはできません。
- prepare_rhs¶
デフォルトは
Trueです。rhsがプレーンな値の場合、prepare_rhsはクエリのパラメータとして使用するために、その値を準備するかどうかを決定します。そのために、lhs.output_field.get_prep_value()が定義されていれば呼び出され、そうでなければrhsはValue()でラップされます。
- process_lhs(compiler, connection, lhs=None)[ソース]¶
compiler.compile(lhs)が返すタプル(lhs_string, lhs_params)を返します。このメソッドをオーバーライドすることで、lhsの処理方法を調整できます。compilerはSQLCompilerオブジェクトで、lhsをコンパイルする際にcompiler.compile(lhs)のように使用します。connectionはベンダ固有の SQL をコンパイルする際に使用します。lhsがNoneでない場合は、self.lhsの代わりにlhsを使用します。
- process_rhs(compiler, connection)[ソース]¶
右辺については
process_lhs()と同じように扱います。