{"title":"カスタムのルックアップを書く","version":"6.0","locale":"ja","docname":"howto/custom-lookups","url":"/ja/6.0/howto/custom-lookups/","canonical":"https://djangodocs.dev/ja/6.0/howto/custom-lookups/","summary":"Django には (たとえば exact や icontains などの) フィルタリングを行う 組み込みのルックアップ がたくさんあります。このドキュメントでは、カスタムルックアップを作る方法や、既存のルックアップの動作を変更する方法について説明します。ルックアップの API リファレンスについては ルックアップ API…","html":"<h1>カスタムのルックアップを書く<a class=\"heading-anchor\" href=\"#how-to-write-custom-lookups\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django には (たとえば <code class=\"docutils literal notranslate\"><span class=\"pre\">exact</span></code> や <code class=\"docutils literal notranslate\"><span class=\"pre\">icontains</span></code> などの) フィルタリングを行う <a class=\"reference internal\" href=\"/ja/6.0/ref/models/querysets/#field-lookups\"><span class=\"std std-ref\">組み込みのルックアップ</span></a> がたくさんあります。このドキュメントでは、カスタムルックアップを作る方法や、既存のルックアップの動作を変更する方法について説明します。ルックアップの API リファレンスについては <a class=\"reference internal\" href=\"/ja/6.0/ref/models/lookups/\"><span class=\"doc\">ルックアップ API リファレンス</span></a> を参照してください。</p>\n<section id=\"a-lookup-example\">\n<h2>ルックアップの例<a class=\"heading-anchor\" href=\"#a-lookup-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>簡単なカスタムルックアップから始めましょう。<code class=\"docutils literal notranslate\"><span class=\"pre\">exact</span></code> と逆の動作をするカスタムルックアップ <code class=\"docutils literal notranslate\"><span class=\"pre\">ne</span></code> を実装していきます。 <code class=\"docutils literal notranslate\"><span class=\"pre\">Author.objects.filter(name__ne='Jack')</span></code> は次の SQL に変換されます。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"ss\">&quot;author&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;name&quot;</span><span class=\"w\"> </span><span class=\"o\">&lt;&gt;</span><span class=\"w\"> </span><span class=\"s1\">&#39;Jack&#39;</span>\n</code></pre></div>\n<p>この SQL はバックエンドに依存しない書き方になっているため、別のデータベースについて心配する必要はありません。</p>\n<p>カスタムルックアップを動作させるためには2つのステップが必要です。まず最初にルックアップを実装し、続いてDjangoに実装したルックアップを認識させる必要があります。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Lookup</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">NotEqual</span><span class=\"p\">(</span><span class=\"n\">Lookup</span><span class=\"p\">):</span>\n    <span class=\"n\">lookup_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;ne&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">lhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_lhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">rhs</span><span class=\"p\">,</span> <span class=\"n\">rhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_rhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"n\">lhs_params</span> <span class=\"o\">+</span> <span class=\"n\">rhs_params</span>\n        <span class=\"k\">return</span> <span class=\"s2\">&quot;</span><span class=\"si\">%s</span><span class=\"s2\"> &lt;&gt; </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">rhs</span><span class=\"p\">),</span> <span class=\"n\">params</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> ルックアップを登録するために、ルックアップを有効にしたいフィールドクラスの <code class=\"docutils literal notranslate\"><span class=\"pre\">register_lookup</span></code> を呼び出す必要があります。今回実装したルックアップは <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> クラスの全てのサブクラスに適用できるため、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> クラスに直接登録しましょう。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Field</span>\n\n<span class=\"n\">Field</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">NotEqual</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>ルックアップの登録は、デコレーターパターンを使って行うこともできます。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Field</span>\n\n\n<span class=\"nd\">@Field</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">NotEqualLookup</span><span class=\"p\">(</span><span class=\"n\">Lookup</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>これ以降、どのようなフィールドであっても <code class=\"docutils literal notranslate\"><span class=\"pre\">foo</span></code> に対しては <code class=\"docutils literal notranslate\"><span class=\"pre\">foo__ne</span></code> が利用できます。なお、これを用いるクエリーセットを生成するならば、それ以前にルックアップの登録を行っておく必要があります。実装する場所は <code class=\"docutils literal notranslate\"><span class=\"pre\">models.py</span></code> ファイル内で行ってもよいし、<code class=\"docutils literal notranslate\"><span class=\"pre\">AppConfig</span></code> 内の <code class=\"docutils literal notranslate\"><span class=\"pre\">ready()</span></code> メソッドにてルックアップの登録を行うのでも構いません。</p>\n<p>実装の詳細について見ると、最初に必要な属性は <code class=\"docutils literal notranslate\"><span class=\"pre\">lookup_name</span></code> です。この属性があると、ORM が <code class=\"docutils literal notranslate\"><span class=\"pre\">name_ne</span></code> を解釈できるようになり、<code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> を使って SQL を生成できます。慣習として、こうした名前は常に小文字のアルファベットのみからなる文字列にしますが、必ず守らなければならない制約は、文字列 <code class=\"docutils literal notranslate\"><span class=\"pre\">__</span></code> を決して含んではならないということです。</p>\n<p>次に、&quot;as_sql&quot; メソッドを定義する必要があります。これには &quot;compiler&quot; という &quot;SQL Compiler&quot; オブジェクトと、アクティブなデータベース接続を必要とします。&quot;SQL Compiler&quot; オブジェクトについてのドキュメントはありませんが、それがSQL文字列を含むタプルと文字列に挿入されるパラメータを返す <code class=\"docutils literal notranslate\"><span class=\"pre\">compile()</span></code> メソッドを持つ、ということだけ知っていれば十分です。ほとんどの場合、これを直接用いる必要はなく、<code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs()</span></code> および <code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs()</span></code> に渡すことができます。</p>\n<p>2つの値に対して動作するルックアップ <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs</span></code> は、それぞれ left-hand side (左辺) と right-hand side (右辺) を表します。左辺は通常フィールド参照ですが、<a class=\"reference internal\" href=\"/ja/6.0/ref/models/lookups/#query-expression\"><span class=\"std std-ref\">クエリ式 API</span></a> を実装するものであれば何でもかまいません。右辺はユーザーから与えられた値です。<code class=\"docutils literal notranslate\"><span class=\"pre\">Author.objects.filter(name__ne='Jack')</span></code> の例では、左辺は <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> モデルの <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> フィールドへの参照で、右辺は <code class=\"docutils literal notranslate\"><span class=\"pre\">'Jack'</span></code> です。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs</span></code>  を呼び出して、前述の <code class=\"docutils literal notranslate\"><span class=\"pre\">compiler</span></code> オブジェクトを使用してSQLに必要な値に変換します。これらのメソッドは、SQL とその SQL に補間されるパラメーターを含むタプルを返します。これは、<code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql</span></code> メソッドが返す必要があるものと同じです。上記の例では、<code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">('&quot;author&quot;.&quot;name&quot;',</span> <span class=\"pre\">[])</span></code> を返し、<code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">('&quot;%s&quot;',</span> <span class=\"pre\">['Jack'])</span></code> を返します。この例では、左側にパラメーターはありませんが、これは所有するオブジェクトに依存するため、返すパラメーターにそれらを含める必要があります。</p>\n<p>最後に、これらの部分を <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;&gt;</span></code> を使って SQL 式にまとめ、クエリのすべてのパラメータを指定します。その後、生成された SQL 文字列とパラメータを含むタプルを返します。</p>\n</section>\n<section id=\"a-transformer-example\">\n<h2>トランスフォーム（<code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>: 変換）の例<a class=\"heading-anchor\" href=\"#a-transformer-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>上記のカスタムルックアップは素晴らしいですが、場合によってはルックアップを一緒に連結したいこともあります。たとえば、<code class=\"docutils literal notranslate\"><span class=\"pre\">abs()</span></code> 演算子を利用したいアプリケーションを構築しているとしましょう。開始値、終了値モデルおよび変更 (start - end) を記録する <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment</span></code> モデルがあります。変化が一定の量に等しい (<code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs=27)</span></code>)、またはそれが一定の量を超えなかった (<code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></code>) すべての Experiment を見つけたいと思うことがあるでしょう。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>この例は多少工夫がされていますが、データベースバックエンドに依存しない方法で、そしてすでに Django にある機能を複製することなく可能な機能の範囲をうまく示しています。</p>\n</aside>\n<p>私たちは <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> トランスフォーマー（変換器）を書くことから始めましょう。次のコードは、 SQL 関数 <code class=\"docutils literal notranslate\"><span class=\"pre\">ABS()</span></code> を使って比較の前に値を変換します:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Transform</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AbsoluteValue</span><span class=\"p\">(</span><span class=\"n\">Transform</span><span class=\"p\">):</span>\n    <span class=\"n\">lookup_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;abs&quot;</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;ABS&quot;</span>\n</code></pre></div>\n<p>次に、<code class=\"docutils literal notranslate\"><span class=\"pre\">IntegerField</span></code> に登録しましょう。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">IntegerField</span>\n\n<span class=\"n\">IntegerField</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">AbsoluteValue</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>これで、このクエリを使うことができるようになりました。 <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs=27)</span></code> は次のSQLを生成します。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">...</span><span class=\"w\"> </span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"mi\">27</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">LookUp</span></code> の代わりに <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> を使うことで、それ以降のルックアップを連結できます。つまり、<code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></code> は以下のようなSQLを生成します。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">...</span><span class=\"w\"> </span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"mi\">27</span>\n</code></pre></div>\n<p>他にルックアップが指定されていない場合、Django は <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs=27</span></code> を <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs__exact=27</span></code> として解釈します。</p>\n<p>これにより <code class=\"docutils literal notranslate\"><span class=\"pre\">ORDER</span> <span class=\"pre\">BY</span></code> 句と <code class=\"docutils literal notranslate\"><span class=\"pre\">DISTINCT</span> <span class=\"pre\">ON</span></code> 句の使用も可能です。例えば <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.order_by('change__abs')</span></code> は以下の SQL を生成します。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">...</span><span class=\"w\"> </span><span class=\"k\">ORDER</span><span class=\"w\"> </span><span class=\"k\">BY</span><span class=\"w\"> </span><span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">ASC</span>\n</code></pre></div>\n<p>そして、PosgreSQL のようにフィールドを DISTINCT することもサポートしています。<code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.distinct('change__abs')</span></code> は以下の SQL を生成します。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">...</span><span class=\"w\"> </span><span class=\"k\">DISTINCT</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"k\">ABS</span><span class=\"p\">(</span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> が適用された後、どのルックアップが許可されるかを探すとき、Django は <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code> 属性を使用します。ここでは変更しないため、これを指定する必要はありませんでしたが、より複雑な型（たとえば、原点に関連する点や複素数）を表すフィールドに <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> を適用すると仮定します。 次に、トランスフォームが次のルックアップのために <code class=\"docutils literal notranslate\"><span class=\"pre\">FloatField</span></code> 型を返すように指定したいかもしれません。これは、次のようにトランスフォームに <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code> 属性を追加することで実現できます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">FloatField</span><span class=\"p\">,</span> <span class=\"n\">Transform</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AbsoluteValue</span><span class=\"p\">(</span><span class=\"n\">Transform</span><span class=\"p\">):</span>\n    <span class=\"n\">lookup_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;abs&quot;</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;ABS&quot;</span>\n\n    <span class=\"nd\">@property</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">output_field</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">FloatField</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>これにより <code class=\"docutils literal notranslate\"><span class=\"pre\">abs__lte</span></code> のようなそれ以降のルックアップが <code class=\"docutils literal notranslate\"><span class=\"pre\">FloatField</span></code> の場合と同じように動作することが保証されます。</p>\n</section>\n<section id=\"writing-an-efficient-abs-lt-lookup\">\n<h2>効率的な <code class=\"docutils literal notranslate\"><span class=\"pre\">abs__lt</span></code> ルックアップを書く<a class=\"heading-anchor\" href=\"#writing-an-efficient-abs-lt-lookup\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>上記の <code class=\"docutils literal notranslate\"><span class=\"pre\">abs</span></code> ルックアップを使用するとき、生成された SQL はいくつかのケースでインデックスを効率的に使用しません。特に、<code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs__lt=27</span></code> を使うとき、これは <code class=\"docutils literal notranslate\"><span class=\"pre\">change__gt=-27</span></code> かつ <code class=\"docutils literal notranslate\"><span class=\"pre\">change__lt=27</span></code> と同じです (<code class=\"docutils literal notranslate\"><span class=\"pre\">lte</span></code> の場合はSQLの <code class=\"docutils literal notranslate\"><span class=\"pre\">BETWEEN</span></code> を使うことができます)。</p>\n<p>そのため、<code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></code> に次のような SQL を生成させたいです。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">..</span><span class=\"w\"> </span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"w\"> </span><span class=\"o\">&lt;</span><span class=\"w\"> </span><span class=\"mi\">27</span><span class=\"w\"> </span><span class=\"k\">AND</span><span class=\"w\"> </span><span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span><span class=\"w\"> </span><span class=\"o\">&gt;</span><span class=\"w\"> </span><span class=\"o\">-</span><span class=\"mi\">27</span>\n</code></pre></div>\n<p>実装は次のようになります。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Lookup</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AbsoluteValueLessThan</span><span class=\"p\">(</span><span class=\"n\">Lookup</span><span class=\"p\">):</span>\n    <span class=\"n\">lookup_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;lt&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n        <span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">lhs_params</span> <span class=\"o\">=</span> <span class=\"n\">compiler</span><span class=\"o\">.</span><span class=\"n\">compile</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">lhs</span><span class=\"o\">.</span><span class=\"n\">lhs</span><span class=\"p\">)</span>\n        <span class=\"n\">rhs</span><span class=\"p\">,</span> <span class=\"n\">rhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_rhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"n\">lhs_params</span> <span class=\"o\">+</span> <span class=\"n\">rhs_params</span> <span class=\"o\">+</span> <span class=\"n\">lhs_params</span> <span class=\"o\">+</span> <span class=\"n\">rhs_params</span>\n        <span class=\"k\">return</span> <span class=\"s2\">&quot;</span><span class=\"si\">%s</span><span class=\"s2\"> &lt; </span><span class=\"si\">%s</span><span class=\"s2\"> AND </span><span class=\"si\">%s</span><span class=\"s2\"> &gt; -</span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">rhs</span><span class=\"p\">,</span> <span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">rhs</span><span class=\"p\">),</span> <span class=\"n\">params</span>\n\n\n<span class=\"n\">AbsoluteValue</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">AbsoluteValueLessThan</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>注目すべきことがいくつかあります。 まず、<code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValueLessThan</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs()</span></code> を呼び出していません。 代わりに、 <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> によって行われた <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> の変換をスキップし、元の <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> を使用します。 つまり、<code class=\"docutils literal notranslate\"><span class=\"pre\">ABS(&quot;experiments&quot;.&quot;change&quot;)</span></code> ではなく、 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;experiments&quot;.&quot;change&quot;</span></code> を取得する必要があります。<code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValueLessThan</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> ルックアップからのみアクセスできるため、 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.lhs.lhs</span></code> を直接参照することは安全です。つまり、 <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> は常に <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> のインスタンスです 。</p>\n<p>また、クエリで両側が複数回使用されているので、paramsは <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs_params</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs_params</span></code> を複数回含む必要があることにも注意してください。</p>\n<p>最後の問い合わせはデータベース内で直接反転（<code class=\"docutils literal notranslate\"><span class=\"pre\">27</span></code> から <code class=\"docutils literal notranslate\"><span class=\"pre\">-27</span></code>）を行います。これを行う理由は、 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.rhs</span></code> が普通の整数値（例えば <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 参照）以外のものである場合、Pythonでは変換ができないためです。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>実際のところ、 <code class=\"docutils literal notranslate\"><span class=\"pre\">__abs</span></code> を使ったルックアップは、このように範囲クエリとして実装することができます。そして、ほとんどのデータベースバックエンドでは、インデックスを利用できるようにするほうが賢明です。しかしPostgreSQLでは、 <code class=\"docutils literal notranslate\"><span class=\"pre\">abs(change)</span></code> にインデックスを追加することをお勧めします。これにより、これらのクエリは非常に効率的になります。</p>\n</aside>\n</section>\n<section id=\"a-bilateral-transformer-example\">\n<h2>双方向のトランスフォームの例<a class=\"heading-anchor\" href=\"#a-bilateral-transformer-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>前に説明した <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> の例は、ルックアップの左側に適用される変換です。 変換を左側と右側の両方に適用したい場合があります。 たとえば、一部のSQL関数に左右されない左側と右側の同等性に基づいてクエリセットをフィルタリングする場合です。</p>\n<p>ここで、大文字小文字を区別しないトランスフォームを試してみましょう。Djangoには既に大文字小文字を区別しないルックアップが多数組み込まれているので、プラクティスとしては良い例ではありません。しかし、データベースにとらわれない双方向のトランスフォームとしては良い例でしょう。</p>\n<p>SQL関数 <code class=\"docutils literal notranslate\"><span class=\"pre\">UPPER()</span></code> を使用して比較前に値を変換する <code class=\"docutils literal notranslate\"><span class=\"pre\">UpperCase</span></code> トランスフォーマーを定義します。 <a class=\"reference internal\" href=\"/ja/6.0/ref/models/lookups/#django.db.models.Transform.bilateral\" title=\"django.db.models.Transform.bilateral\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">bilateral</span> <span class=\"pre\">=</span> <span class=\"pre\">True</span></code></a> を定義して、この変換が <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs</span></code> の両方に適用されることを示します:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Transform</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UpperCase</span><span class=\"p\">(</span><span class=\"n\">Transform</span><span class=\"p\">):</span>\n    <span class=\"n\">lookup_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;upper&quot;</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;UPPER&quot;</span>\n    <span class=\"n\">bilateral</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n</code></pre></div>\n<p>次に、それを登録しましょう:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">CharField</span><span class=\"p\">,</span> <span class=\"n\">TextField</span>\n\n<span class=\"n\">CharField</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">UpperCase</span><span class=\"p\">)</span>\n<span class=\"n\">TextField</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">UpperCase</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>これで、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Author.objects.filter(name__upper=&quot;doe&quot;)</span></code> は次のような大文字小文字を区別しないクエリを生成するようになります。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">...</span><span class=\"w\"> </span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"k\">UPPER</span><span class=\"p\">(</span><span class=\"ss\">&quot;author&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;name&quot;</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"k\">UPPER</span><span class=\"p\">(</span><span class=\"s1\">&#39;doe&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"writing-alternative-implementations-for-existing-lookups\">\n<h2>既存のルックアップに代替の実装を書く<a class=\"heading-anchor\" href=\"#writing-alternative-implementations-for-existing-lookups\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>異なるデータベースベンダーは、同じ操作に対して異なるSQLを必要とする場合があります。 この例では、MySQLのNotEqual演算子のカスタム実装を書き換えます。<code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;&gt;</span></code> の代わりに <code class=\"docutils literal notranslate\"><span class=\"pre\">!=</span></code> 演算子を使用します。 （実際には、Djangoがサポートするすべての公式データベースを含め、ほとんどすべてのデータベースが両方をサポートしていることに注意してください）。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">as_mysql</span></code> メソッドで <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> のサブクラスを作成することで、特定のバックエンドの振る舞いを変えることができます。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MySQLNotEqual</span><span class=\"p\">(</span><span class=\"n\">NotEqual</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">as_mysql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">extra_context</span><span class=\"p\">):</span>\n        <span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">lhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_lhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">rhs</span><span class=\"p\">,</span> <span class=\"n\">rhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_rhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"n\">lhs_params</span> <span class=\"o\">+</span> <span class=\"n\">rhs_params</span>\n        <span class=\"k\">return</span> <span class=\"s2\">&quot;</span><span class=\"si\">%s</span><span class=\"s2\"> != </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">rhs</span><span class=\"p\">),</span> <span class=\"n\">params</span>\n\n\n<span class=\"n\">Field</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">MySQLNotEqual</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>そしてそれを <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code> に登録することができます。元の <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> クラスが同じ <code class=\"docutils literal notranslate\"><span class=\"pre\">lookup_name</span></code> を持つので代わりに使われます。</p>\n<p>クエリをコンパイルするとき、Djangoは最初に <code class=\"docutils literal notranslate\"><span class=\"pre\">as_%s</span> <span class=\"pre\">%</span> <span class=\"pre\">connection.vendor</span></code> メソッドを探し、それから <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql</span></code> にフォールバックします。組み込みのバックエンドのベンダ名は <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlite</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">postgresql</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">oracle</span></code> および <code class=\"docutils literal notranslate\"><span class=\"pre\">mysql</span></code> です。</p>\n</section>\n<section id=\"how-django-determines-the-lookups-and-transforms-which-are-used\">\n<h2>Django はどうやってルックアップとトランスフォームのどちらを使うかを決定するのか？<a class=\"heading-anchor\" href=\"#how-django-determines-the-lookups-and-transforms-which-are-used\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>場合によっては、修正するのではなく、渡された名前に基づいて、どの <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> または <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> を返すかを動的に変更したい場合があります。 例として、座標または任意の次元を格納するフィールドがあり、 <code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(coords__x7=4)</span></code> のような構文で、7番目の座標の値が4であるオブジェクトを返すことができます。 これを行うには、次のようなもので <code class=\"docutils literal notranslate\"><span class=\"pre\">get_lookup</span></code> をオーバーライドします:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CoordinatesField</span><span class=\"p\">(</span><span class=\"n\">Field</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_lookup</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">lookup_name</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"n\">lookup_name</span><span class=\"o\">.</span><span class=\"n\">startswith</span><span class=\"p\">(</span><span class=\"s2\">&quot;x&quot;</span><span class=\"p\">):</span>\n            <span class=\"k\">try</span><span class=\"p\">:</span>\n                <span class=\"n\">dimension</span> <span class=\"o\">=</span> <span class=\"nb\">int</span><span class=\"p\">(</span><span class=\"n\">lookup_name</span><span class=\"o\">.</span><span class=\"n\">removeprefix</span><span class=\"p\">(</span><span class=\"s2\">&quot;x&quot;</span><span class=\"p\">))</span>\n            <span class=\"k\">except</span> <span class=\"ne\">ValueError</span><span class=\"p\">:</span>\n                <span class=\"k\">pass</span>\n            <span class=\"k\">else</span><span class=\"p\">:</span>\n                <span class=\"k\">return</span> <span class=\"n\">get_coordinate_lookup</span><span class=\"p\">(</span><span class=\"n\">dimension</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_lookup</span><span class=\"p\">(</span><span class=\"n\">lookup_name</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>それから、適切な <code class=\"docutils literal notranslate\"><span class=\"pre\">dimension</span></code> の値を扱う <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> サブクラスを返すように <code class=\"docutils literal notranslate\"><span class=\"pre\">get_coordinate_lookup</span></code> を適切に定義します。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_transform()</span></code> という似た名前のメソッドもあります。 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_lookup()</span></code> は常に <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> サブクラスを返し、 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_transform()</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> サブクラスを返す必要があります。 <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> オブジェクトはさらにフィルタできますが、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> オブジェクトはそれ以上フィルタできないことに注意してください。</p>\n<p>フィルタリングする際に、解決すべきルックアップ名が1つしか残っていない場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> を探します。複数の名前がある場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> を探します。名前が1つしかなく、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> が見つからない場合は、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> を探し、その <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> に対して <code class=\"docutils literal notranslate\"><span class=\"pre\">exact</span></code> ルックアップを行います。すべての呼び出しシーケンスは常に <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> で終わります。これは、以下のことを明確にするためです:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(myfield__mylookup)</span></code> が <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_lookup('mylookup')</span></code> を呼び出すこと。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(myfield__mytransform__mylookup)</span></code> が <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_transform('mytransform')</span></code> を呼び出し、次に <code class=\"docutils literal notranslate\"><span class=\"pre\">mytransform.get_lookup('mylookup')</span></code> を呼び出すこと。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(myfield__mytransform)</span></code> が最初に <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_lookup('mytransform')</span></code> を呼び出そうとして失敗し、そのため <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_transform('mytransform')</span></code> 、次に <code class=\"docutils literal notranslate\"><span class=\"pre\">mytransform.get_lookup('exact')</span></code> をフォールバックとして呼び出すこと。</p></li>\n</ul>\n</section>","rootId":"how-to-write-custom-lookups","toc":[{"title":"ルックアップの例","anchor":"a-lookup-example","children":[]},{"title":"トランスフォーム（Transform: 変換）の例","anchor":"a-transformer-example","children":[]},{"title":"効率的な abs__lt ルックアップを書く","anchor":"writing-an-efficient-abs-lt-lookup","children":[]},{"title":"双方向のトランスフォームの例","anchor":"a-bilateral-transformer-example","children":[]},{"title":"既存のルックアップに代替の実装を書く","anchor":"writing-alternative-implementations-for-existing-lookups","children":[]},{"title":"Django はどうやってルックアップとトランスフォームのどちらを使うかを決定するのか？","anchor":"how-django-determines-the-lookups-and-transforms-which-are-used","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"How-to ガイド","url":"/ja/6.0/howto/"}],"prev":{"docname":"howto/writing-migrations","title":"データベースのマイグレーションの作成方法","url":"/ja/6.0/howto/writing-migrations/"},"next":{"docname":"howto/outputting-csv","title":"CSVを出力する","url":"/ja/6.0/howto/outputting-csv/"},"formats":{"html":"/ja/6.0/howto/custom-lookups/","markdown":"/ja/6.0/howto/custom-lookups.md","json":"/ja/6.0/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/ja/6.0/howto/custom-lookups/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}