{"title":"Własne listy rozwijane","version":"2.2","locale":"pl","docname":"howto/custom-lookups","url":"/pl/2.2/howto/custom-lookups/","canonical":"https://djangodocs.dev/pl/2.2/howto/custom-lookups/","summary":"Django offers a wide variety of built-in lookups for filtering (for example, exact and icontains).","html":"<h1>Własne listy rozwijane<a class=\"heading-anchor\" href=\"#custom-lookups\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django offers a wide variety of <a class=\"reference internal\" href=\"/pl/2.2/ref/models/querysets/#field-lookups\"><span class=\"std std-ref\">built-in lookups</span></a> for\nfiltering (for example, <code class=\"docutils literal notranslate\">exact</code> and <code class=\"docutils literal notranslate\">icontains</code>). This documentation\nexplains how to write custom lookups and how to alter the working of existing\nlookups. For the API references of lookups, see the <a class=\"reference internal\" href=\"/pl/2.2/ref/models/lookups/\"><span class=\"doc\">Lookup API reference</span></a>.</p>\n<section id=\"a-simple-lookup-example\">\n<h2>Prosty przykład wyszukiwania<a class=\"heading-anchor\" href=\"#a-simple-lookup-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Zacznijmy od prostego niestandardowego wyszukiwania. Napiszemy wyszukiwanie  <code class=\"docutils literal notranslate\">ne</code>, które działa przeciwnie do <code class=\"docutils literal notranslate\">exact</code>. <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>Author.objects.filter(name__ne=»Jack»)``co będzie przetłumaczone do SQL:</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=\"s2\">&quot;author&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;name&quot;</span> <span class=\"o\">&lt;&gt;</span> <span class=\"s1\">&#39;Jack&#39;</span>\n</code></pre></div>\n<p>Backend SQL jest niezależny, dlatego nie musimy martwić się o różne bazy danych</p>\n<p>Są tutaj dwa kroki do zrobienia tej pracy. Po pierwsze potrzebujemy zaimplementować wyszukiwanie, a potem potrzebujemy powiedzieć o tym Django. Implementacja jest całkiem prosta:</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Lookup\n\n<span class=\"k\">class</span> <span class=\"nc\">NotEqual</span><span class=\"p\">(</span>Lookup<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;ne&#39;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> compiler<span class=\"p\">,</span> connection<span class=\"p\">):</span>\n        lhs<span class=\"p\">,</span> lhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_lhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        rhs<span class=\"p\">,</span> rhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_rhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        params <span class=\"o\">=</span> lhs_params <span class=\"o\">+</span> rhs_params\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> &lt;&gt; </span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>lhs<span class=\"p\">,</span> rhs<span class=\"p\">),</span> params\n</code></pre></div>\n<p>Aby zarejestrować wyszukiwanie <code class=\"docutils literal notranslate\">NotEqual</code>, należy wywołać <code class=\"docutils literal notranslate\">register_lookup</code> na klasie pola, która ma być dostępna. W tym przypadku wyszukiwanie ma sens we wszystkich podklasach <code class=\"docutils literal notranslate\">Field</code>, więc rejestrujemy je bezpośrednio <code class=\"docutils literal notranslate\">Field</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=\"nn\">django.db.models.fields</span> <span class=\"kn\">import</span> Field\nField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>NotEqual<span class=\"p\">)</span>\n</code></pre></div>\n<p>Wyszukiwanie może zostać wykonany używając wzorca dekorator:</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=\"nn\">django.db.models.fields</span> <span class=\"kn\">import</span> Field\n\n<span class=\"nd\">@Field</span><span class=\"o\">.</span>register_lookup\n<span class=\"k\">class</span> <span class=\"nc\">NotEqualLookup</span><span class=\"p\">(</span>Lookup<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n</code></pre></div>\n<p>We can now use <code class=\"docutils literal notranslate\">foo__ne</code> for any field <code class=\"docutils literal notranslate\">foo</code>. You will need to ensure that\nthis registration happens before you try to create any querysets using it. You\ncould place the implementation in a <code class=\"docutils literal notranslate\">models.py</code> file, or register the lookup\nin the <code class=\"docutils literal notranslate\">ready()</code> method of an <code class=\"docutils literal notranslate\">AppConfig</code>.</p>\n<p>Taking a closer look at the implementation, the first required attribute is\n<code class=\"docutils literal notranslate\">lookup_name</code>. This allows the ORM to understand how to interpret <code class=\"docutils literal notranslate\">name__ne</code>\nand use <code class=\"docutils literal notranslate\">NotEqual</code> to generate the SQL. By convention, these names are always\nlowercase strings containing only letters, but the only hard requirement is\nthat it must not contain the string <code class=\"docutils literal notranslate\">__</code>.</p>\n<p>We then need to define the <code class=\"docutils literal notranslate\">as_sql</code> method. This takes a <code class=\"docutils literal notranslate\">SQLCompiler</code>\nobject, called <code class=\"docutils literal notranslate\">compiler</code>,  and the active database connection.\n<code class=\"docutils literal notranslate\">SQLCompiler</code> objects are not documented, but the only thing we need to know\nabout them is that they have a <code class=\"docutils literal notranslate\">compile()</code> method which returns a tuple\ncontaining an SQL string, and the parameters to be interpolated into that\nstring. In most cases, you don’t need to use it directly and can pass it on to\n<code class=\"docutils literal notranslate\">process_lhs()</code> and <code class=\"docutils literal notranslate\">process_rhs()</code>.</p>\n<p>A <code class=\"docutils literal notranslate\">Lookup</code> works against two values, <code class=\"docutils literal notranslate\">lhs</code> and <code class=\"docutils literal notranslate\">rhs</code>, standing for\nleft-hand side and right-hand side. The left-hand side is usually a field\nreference, but it can be anything implementing the <a class=\"reference internal\" href=\"/pl/2.2/ref/models/lookups/#query-expression\"><span class=\"std std-ref\">query expression API</span></a>. The right-hand is the value given by the user. In the\nexample <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code>, the left-hand side is a\nreference to the <code class=\"docutils literal notranslate\">name</code> field of the <code class=\"docutils literal notranslate\">Author</code> model, and <code class=\"docutils literal notranslate\">'Jack'</code> is the\nright-hand side.</p>\n<p>We call <code class=\"docutils literal notranslate\">process_lhs</code> and <code class=\"docutils literal notranslate\">process_rhs</code> to convert them into the values we\nneed for SQL using the <code class=\"docutils literal notranslate\">compiler</code> object described before. These methods\nreturn tuples containing some SQL and the parameters to be interpolated into\nthat SQL, just as we need to return from our <code class=\"docutils literal notranslate\">as_sql</code> method. In the above\nexample, <code class=\"docutils literal notranslate\">process_lhs</code> returns <code class=\"docutils literal notranslate\">('&quot;author&quot;.&quot;name&quot;', [])</code> and\n<code class=\"docutils literal notranslate\">process_rhs</code> returns <code class=\"docutils literal notranslate\">('&quot;%s&quot;', ['Jack'])</code>. In this example there were no\nparameters for the left hand side, but this would depend on the object we have,\nso we still need to include them in the parameters we return.</p>\n<p>Finalnie łączymy poszczególnie części w wyrażenie SQL używając <code class=\"docutils literal notranslate\">&lt;&gt;</code> i zapewniamy wszystkie parametry do zapytania. Następnie zwracamy tuplę zawierającą wygenerowany łańcuch znaków SQL i parametry.</p>\n</section>\n<section id=\"a-simple-transformer-example\">\n<h2>Przykład prostego transformatora<a class=\"heading-anchor\" href=\"#a-simple-transformer-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The custom lookup above is great, but in some cases you may want to be able to\nchain lookups together. For example, let’s suppose we are building an\napplication where we want to make use of the <code class=\"docutils literal notranslate\">abs()</code> operator.\nWe have an <code class=\"docutils literal notranslate\">Experiment</code> model which records a start value, end value, and the\nchange (start - end). We would like to find all experiments where the change\nwas equal to a certain amount (<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code>),\nor where it did not exceed a certain amount\n(<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code>).</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Informacja</p>\n<p>This example is somewhat contrived, but it nicely demonstrates the range of\nfunctionality which is possible in a database backend independent manner,\nand without duplicating functionality already in Django.</p>\n</aside>\n<p>Zaczniemy od napisania transformatora <code class=\"docutils literal notranslate\">AbsoluteValue. Będzie on używał funckji SQL ``ABS()</code> do przekształcania wartości przed porównaniem:</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Transform\n\n<span class=\"k\">class</span> <span class=\"nc\">AbsoluteValue</span><span class=\"p\">(</span>Transform<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;abs&#39;</span>\n    function <span class=\"o\">=</span> <span class=\"s1\">&#39;ABS&#39;</span>\n</code></pre></div>\n<p>Next, let’s register it for <code class=\"docutils literal notranslate\">IntegerField</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> IntegerField\nIntegerField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>AbsoluteValue<span class=\"p\">)</span>\n</code></pre></div>\n<p>Teraz możemy wykonać zapytanie, które napisaliśmy wcześniej. <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code> wygeneruje następujący SQL:</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>SELECT <span class=\"o\">...</span> WHERE ABS<span class=\"p\">(</span><span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span><span class=\"p\">)</span> <span class=\"o\">=</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>By using <code class=\"docutils literal notranslate\">Transform</code> instead of <code class=\"docutils literal notranslate\">Lookup</code> it means we are able to chain\nfurther lookups afterwards. So\n<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> will generate the following\nSQL:</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>SELECT <span class=\"o\">...</span> WHERE ABS<span class=\"p\">(</span><span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span><span class=\"p\">)</span> <span class=\"o\">&lt;</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>Zauważ, że w tym przypadku nie ma innych zdefiniowanych wyszukiwań, Django interpretuje <code class=\"docutils literal notranslate\">change_abs=27</code> jako <code class=\"docutils literal notranslate\">change__abs__exact=27</code>.</p>\n<p>To również umożliwia aby wyniki zostały użyte w wyrażeniach <code class=\"docutils literal notranslate\">ORDER_BY</code> i <code class=\"docutils literal notranslate\">DISTINCT ON</code>. Przykładowo <code class=\"docutils literal notranslate\">Experiment.objects.order_by('change__abs')</code> wygeneruje:</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>SELECT <span class=\"o\">...</span> ORDER BY ABS<span class=\"p\">(</span><span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span><span class=\"p\">)</span> ASC\n</code></pre></div>\n<p>I z bazą danych, która wspiera niepowtarzalność na polach (np. PostgreSQL), <code class=\"docutils literal notranslate\">Experiment.objects.distinct('change__abs')</code> wygeneruje:</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>SELECT <span class=\"o\">...</span> DISTINCT ON ABS<span class=\"p\">(</span><span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"2.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 2.1</p><p>Wsparcie sortowania i niepowtarzalności, jak opisano w poprzednich dwóch paragrafach, zostało dodane.</p>\n</aside>\n<p>When looking for which lookups are allowable after the <code class=\"docutils literal notranslate\">Transform</code> has been\napplied, Django uses the <code class=\"docutils literal notranslate\">output_field</code> attribute. We didn’t need to specify\nthis here as it didn’t change, but supposing we were applying <code class=\"docutils literal notranslate\">AbsoluteValue</code>\nto some field which represents a more complex type (for example a point\nrelative to an origin, or a complex number) then we may have wanted to specify\nthat the transform returns a <code class=\"docutils literal notranslate\">FloatField</code> type for further lookups. This can\nbe done by adding an <code class=\"docutils literal notranslate\">output_field</code> attribute to the transform:</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> FloatField<span class=\"p\">,</span> Transform\n\n<span class=\"k\">class</span> <span class=\"nc\">AbsoluteValue</span><span class=\"p\">(</span>Transform<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;abs&#39;</span>\n    function <span class=\"o\">=</span> <span class=\"s1\">&#39;ABS&#39;</span>\n\n    <span class=\"nd\">@property</span>\n    <span class=\"k\">def</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> FloatField<span class=\"p\">()</span>\n</code></pre></div>\n<p>To zapewnia nas, że kolejne przeszukiwania takie jak <code class=\"docutils literal notranslate\">abs__lte</code> zachowują się tak jak dla <code class=\"docutils literal notranslate\">FloatField</code>.</p>\n</section>\n<section id=\"writing-an-efficient-abs-lt-lookup\">\n<h2>Pisanie efektywnego wyszukiwania <code class=\"docutils literal notranslate\">abs__lt</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>When using the above written <code class=\"docutils literal notranslate\">abs</code> lookup, the SQL produced will not use\nindexes efficiently in some cases. In particular, when we use\n<code class=\"docutils literal notranslate\">change__abs__lt=27</code>, this is equivalent to <code class=\"docutils literal notranslate\">change__gt=-27</code> AND\n<code class=\"docutils literal notranslate\">change__lt=27</code>. (For the <code class=\"docutils literal notranslate\">lte</code> case we could use the SQL <code class=\"docutils literal notranslate\">BETWEEN</code>).</p>\n<p>So we would like <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> to generate\nthe following SQL:</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>SELECT <span class=\"o\">..</span> WHERE <span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span> <span class=\"o\">&lt;</span> <span class=\"mi\">27</span> AND <span class=\"s2\">&quot;experiments&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;change&quot;</span> <span class=\"o\">&gt;</span> <span class=\"o\">-</span><span class=\"mi\">27</span>\n</code></pre></div>\n<p>The implementation is:</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Lookup\n\n<span class=\"k\">class</span> <span class=\"nc\">AbsoluteValueLessThan</span><span class=\"p\">(</span>Lookup<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;lt&#39;</span>\n\n    <span class=\"k\">def</span> <span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> compiler<span class=\"p\">,</span> connection<span class=\"p\">):</span>\n        lhs<span class=\"p\">,</span> lhs_params <span class=\"o\">=</span> compiler<span class=\"o\">.</span>compile<span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>lhs<span class=\"o\">.</span>lhs<span class=\"p\">)</span>\n        rhs<span class=\"p\">,</span> rhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_rhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        params <span class=\"o\">=</span> lhs_params <span class=\"o\">+</span> rhs_params <span class=\"o\">+</span> lhs_params <span class=\"o\">+</span> rhs_params\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> &lt; </span><span class=\"si\">%s</span><span class=\"s1\"> AND </span><span class=\"si\">%s</span><span class=\"s1\"> &gt; -</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>lhs<span class=\"p\">,</span> rhs<span class=\"p\">,</span> lhs<span class=\"p\">,</span> rhs<span class=\"p\">),</span> params\n\nAbsoluteValue<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>AbsoluteValueLessThan<span class=\"p\">)</span>\n</code></pre></div>\n<p>There are a couple of notable things going on. First, <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code>\nisn’t calling <code class=\"docutils literal notranslate\">process_lhs()</code>. Instead it skips the transformation of the\n<code class=\"docutils literal notranslate\">lhs</code> done by <code class=\"docutils literal notranslate\">AbsoluteValue</code> and uses the original <code class=\"docutils literal notranslate\">lhs</code>. That is, we\nwant to get <code class=\"docutils literal notranslate\">&quot;experiments&quot;.&quot;change&quot;</code> not <code class=\"docutils literal notranslate\">ABS(&quot;experiments&quot;.&quot;change&quot;)</code>.\nReferring directly to <code class=\"docutils literal notranslate\">self.lhs.lhs</code> is safe as <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code>\ncan be accessed only from the <code class=\"docutils literal notranslate\">AbsoluteValue</code> lookup, that is the <code class=\"docutils literal notranslate\">lhs</code>\nis always an instance of <code class=\"docutils literal notranslate\">AbsoluteValue</code>.</p>\n<p>Zauważ również, że gdy obie strony używane są w zapytaniu wielokrotnie to parametry muszą zawierać wielokrotnie <code class=\"docutils literal notranslate\">lhs_params</code> i <code class=\"docutils literal notranslate\">rhs_params</code>.</p>\n<p>Ostateczne zapytanie wykonuje odwrócenie wartości (<code class=\"docutils literal notranslate\">27</code> na <code class=\"docutils literal notranslate\">-27</code>) bezpośrednio w bazie danych. Wynika to z faktu, że jeśli <code class=\"docutils literal notranslate\">self.rhs</code> jest czymś innym niż zwykłą wartością liczbową (np. jakąś referencją <code class=\"docutils literal notranslate\">F()</code>), nie możemy dokonać transformacji w Pythonie.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Informacja</p>\n<p>In fact, most lookups with <code class=\"docutils literal notranslate\">__abs</code> could be implemented as range queries\nlike this, and on most database backends it is likely to be more sensible to\ndo so as you can make use of the indexes. However with PostgreSQL you may\nwant to add an index on <code class=\"docutils literal notranslate\">abs(change)</code> which would allow these queries to\nbe very efficient.</p>\n</aside>\n</section>\n<section id=\"a-bilateral-transformer-example\">\n<h2>Przykład dwustronnego transformatora<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>The <code class=\"docutils literal notranslate\">AbsoluteValue</code> example we discussed previously is a transformation which\napplies to the left-hand side of the lookup. There may be some cases where you\nwant the transformation to be applied to both the left-hand side and the\nright-hand side. For instance, if you want to filter a queryset based on the\nequality of the left and right-hand side insensitively to some SQL function.</p>\n<p>Let’s examine the simple example of case-insensitive transformation here. This\ntransformation isn’t very useful in practice as Django already comes with a bunch\nof built-in case-insensitive lookups, but it will be a nice demonstration of\nbilateral transformations in a database-agnostic way.</p>\n<p>We define an <code class=\"docutils literal notranslate\">UpperCase</code> transformer which uses the SQL function <code class=\"docutils literal notranslate\">UPPER()</code> to\ntransform the values before comparison. We define\n<a class=\"reference internal\" href=\"/pl/2.2/ref/models/lookups/#django.db.models.Transform.bilateral\" title=\"django.db.models.Transform.bilateral\"><code class=\"xref py py-attr docutils literal notranslate\">bilateral = True</code></a> to indicate that\nthis transformation should apply to both <code class=\"docutils literal notranslate\">lhs</code> and <code class=\"docutils literal notranslate\">rhs</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Transform\n\n<span class=\"k\">class</span> <span class=\"nc\">UpperCase</span><span class=\"p\">(</span>Transform<span class=\"p\">):</span>\n    lookup_name <span class=\"o\">=</span> <span class=\"s1\">&#39;upper&#39;</span>\n    function <span class=\"o\">=</span> <span class=\"s1\">&#39;UPPER&#39;</span>\n    bilateral <span class=\"o\">=</span> <span class=\"kc\">True</span>\n</code></pre></div>\n<p>Next, let’s register it:</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> CharField<span class=\"p\">,</span> TextField\nCharField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>UpperCase<span class=\"p\">)</span>\nTextField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>UpperCase<span class=\"p\">)</span>\n</code></pre></div>\n<p>Now, the queryset <code class=\"docutils literal notranslate\">Author.objects.filter(name__upper=&quot;doe&quot;)</code> will generate a case\ninsensitive query like this:</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>SELECT <span class=\"o\">...</span> WHERE UPPER<span class=\"p\">(</span><span class=\"s2\">&quot;author&quot;</span><span class=\"o\">.</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">)</span> <span class=\"o\">=</span> UPPER<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>Writing alternative implementations for existing lookups<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>Sometimes different database vendors require different SQL for the same\noperation. For this example we will rewrite a custom implementation for\nMySQL for the NotEqual operator. Instead of <code class=\"docutils literal notranslate\">&lt;&gt;</code> we will be using <code class=\"docutils literal notranslate\">!=</code>\noperator. (Note that in reality almost all databases support both, including\nall the official databases supported by Django).</p>\n<p>We can change the behavior on a specific backend by creating a subclass of\n<code class=\"docutils literal notranslate\">NotEqual</code> with an <code class=\"docutils literal notranslate\">as_mysql</code> method:</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=\"nc\">MySQLNotEqual</span><span class=\"p\">(</span>NotEqual<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">as_mysql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> compiler<span class=\"p\">,</span> connection<span class=\"p\">,</span> <span class=\"o\">**</span>extra_context<span class=\"p\">):</span>\n        lhs<span class=\"p\">,</span> lhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_lhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        rhs<span class=\"p\">,</span> rhs_params <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>process_rhs<span class=\"p\">(</span>compiler<span class=\"p\">,</span> connection<span class=\"p\">)</span>\n        params <span class=\"o\">=</span> lhs_params <span class=\"o\">+</span> rhs_params\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> != </span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span>lhs<span class=\"p\">,</span> rhs<span class=\"p\">),</span> params\n\nField<span class=\"o\">.</span>register_lookup<span class=\"p\">(</span>MySQLNotEqual<span class=\"p\">)</span>\n</code></pre></div>\n<p>We can then register it with <code class=\"docutils literal notranslate\">Field</code>. It takes the place of the original\n<code class=\"docutils literal notranslate\">NotEqual</code> class as it has the same <code class=\"docutils literal notranslate\">lookup_name</code>.</p>\n<p>When compiling a query, Django first looks for <code class=\"docutils literal notranslate\">as_%s % connection.vendor</code>\nmethods, and then falls back to <code class=\"docutils literal notranslate\">as_sql</code>. The vendor names for the in-built\nbackends are <code class=\"docutils literal notranslate\">sqlite</code>, <code class=\"docutils literal notranslate\">postgresql</code>, <code class=\"docutils literal notranslate\">oracle</code> and <code class=\"docutils literal notranslate\">mysql</code>.</p>\n</section>\n<section id=\"how-django-determines-the-lookups-and-transforms-which-are-used\">\n<h2>How Django determines the lookups and transforms which are used<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>In some cases you may wish to dynamically change which <code class=\"docutils literal notranslate\">Transform</code> or\n<code class=\"docutils literal notranslate\">Lookup</code> is returned based on the name passed in, rather than fixing it. As\nan example, you could have a field which stores coordinates or an arbitrary\ndimension, and wish to allow a syntax like <code class=\"docutils literal notranslate\">.filter(coords__x7=4)</code> to return\nthe objects where the 7th coordinate has value 4. In order to do this, you\nwould override <code class=\"docutils literal notranslate\">get_lookup</code> with something like:</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=\"nc\">CoordinatesField</span><span class=\"p\">(</span>Field<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">get_lookup</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> lookup_name<span class=\"p\">):</span>\n        <span class=\"k\">if</span> lookup_name<span class=\"o\">.</span>startswith<span class=\"p\">(</span><span class=\"s1\">&#39;x&#39;</span><span class=\"p\">):</span>\n            <span class=\"k\">try</span><span class=\"p\">:</span>\n                dimension <span class=\"o\">=</span> <span class=\"nb\">int</span><span class=\"p\">(</span>lookup_name<span class=\"p\">[</span><span class=\"mi\">1</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> get_coordinate_lookup<span class=\"p\">(</span>dimension<span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>get_lookup<span class=\"p\">(</span>lookup_name<span class=\"p\">)</span>\n</code></pre></div>\n<p>You would then define <code class=\"docutils literal notranslate\">get_coordinate_lookup</code> appropriately to return a\n<code class=\"docutils literal notranslate\">Lookup</code> subclass which handles the relevant value of <code class=\"docutils literal notranslate\">dimension</code>.</p>\n<p>There is a similarly named method called <code class=\"docutils literal notranslate\">get_transform()</code>. <code class=\"docutils literal notranslate\">get_lookup()</code>\nshould always return a <code class=\"docutils literal notranslate\">Lookup</code> subclass, and <code class=\"docutils literal notranslate\">get_transform()</code> a\n<code class=\"docutils literal notranslate\">Transform</code> subclass. It is important to remember that <code class=\"docutils literal notranslate\">Transform</code>\nobjects can be further filtered on, and <code class=\"docutils literal notranslate\">Lookup</code> objects cannot.</p>\n<p>When filtering, if there is only one lookup name remaining to be resolved, we\nwill look for a <code class=\"docutils literal notranslate\">Lookup</code>. If there are multiple names, it will look for a\n<code class=\"docutils literal notranslate\">Transform</code>. In the situation where there is only one name and a <code class=\"docutils literal notranslate\">Lookup</code>\nis not found, we look for a <code class=\"docutils literal notranslate\">Transform</code> and then the <code class=\"docutils literal notranslate\">exact</code> lookup on that\n<code class=\"docutils literal notranslate\">Transform</code>. All call sequences always end with a <code class=\"docutils literal notranslate\">Lookup</code>. To clarify:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mylookup)</code> will call <code class=\"docutils literal notranslate\">myfield.get_lookup('mylookup')</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mytransform__mylookup)</code> will call\n<code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code>, and then\n<code class=\"docutils literal notranslate\">mytransform.get_lookup('mylookup')</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mytransform)</code> will first call\n<code class=\"docutils literal notranslate\">myfield.get_lookup('mytransform')</code>, which will fail, so it will fall back\nto calling <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code> and then\n<code class=\"docutils literal notranslate\">mytransform.get_lookup('exact')</code>.</p></li>\n</ul>\n</section>","rootId":"custom-lookups","toc":[{"title":"Prosty przykład wyszukiwania","anchor":"a-simple-lookup-example","children":[]},{"title":"Przykład prostego transformatora","anchor":"a-simple-transformer-example","children":[]},{"title":"Pisanie efektywnego wyszukiwania abs__lt","anchor":"writing-an-efficient-abs-lt-lookup","children":[]},{"title":"Przykład dwustronnego transformatora","anchor":"a-bilateral-transformer-example","children":[]},{"title":"Writing alternative implementations for existing lookups","anchor":"writing-alternative-implementations-for-existing-lookups","children":[]},{"title":"How Django determines the lookups and transforms which are used","anchor":"how-django-determines-the-lookups-and-transforms-which-are-used","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"Przewodniki „Jak to zrobić”","url":"/pl/2.2/howto/"}],"prev":{"docname":"howto/custom-model-fields","title":"Writing custom model fields","url":"/pl/2.2/howto/custom-model-fields/"},"next":{"docname":"howto/custom-template-tags","title":"Custom template tags and filters","url":"/pl/2.2/howto/custom-template-tags/"},"formats":{"html":"/pl/2.2/howto/custom-lookups/","markdown":"/pl/2.2/howto/custom-lookups.md","json":"/pl/2.2/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/2.2.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/pl/2.2/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"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}