{"title":"Come scrivere lookup personalizzati","version":"4.0","locale":"it","docname":"howto/custom-lookups","url":"/it/4.0/howto/custom-lookups/","canonical":"https://djangodocs.dev/it/4.0/howto/custom-lookups/","summary":"Django offre una ampia varietà di built-in lookups per la selezione (per esempio, exact e icontains).","html":"<h1>Come scrivere lookup personalizzati<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 offre una ampia varietà di <a class=\"reference internal\" href=\"/it/4.0/ref/models/querysets/#field-lookups\"><span class=\"std std-ref\">built-in lookups</span></a> per la selezione (per esempio, <code class=\"docutils literal notranslate\">exact</code> e <code class=\"docutils literal notranslate\">icontains</code>). Questo documento spiega come scrivere criteri di ricerca personalizzati e come modificare il comportamento di quelli esistenti. Per i riferimenti alle API dei criteri di ricerca, vedi <a class=\"reference internal\" href=\"/it/4.0/ref/models/lookups/\"><span class=\"doc\">Lookup API reference</span></a>.</p>\n<section id=\"a-lookup-example\">\n<h2>Un esempio di criterio di ricerca<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>Iniziamo con un piccolo lookup custom. Scriveremo un lookup custom <code class=\"docutils literal notranslate\">ne</code> che lavora in modo opposto ad <code class=\"docutils literal notranslate\">exact</code>. <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code> si tradurrà nell’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=\"o\">&lt;&gt;</span> <span class=\"s1\">&#39;Jack&#39;</span>\n</code></pre></div>\n<p>Questo comando SQL è indipendente dal backend, non ci dobbiamo quindi preoccupare di differenti basi di dati.</p>\n<p>Sono richiesti due passaggi per farlo funzionare. Primo devi implementare il criterio di ricerca, poi occorre dichiaralo in 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=\"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>Per registrare il lookup <code class=\"docutils literal notranslate\">NotEqual</code> dovremo chiamare <code class=\"docutils literal notranslate\">register_lookup</code> sul campo della classe in cui vogliamo che il lookup sia disponibile. In questo caso, il lookup ha senso su tutte le sottoclassi <code class=\"docutils literal notranslate\">Field</code>, così possiamo registrarlo direttamente con <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</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>La registrazione di un criterio di ricerca si puo” fare anche usando un modello decoratore:</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> 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>Adesso possiamo usare <code class=\"docutils literal notranslate\">foo__ne</code> per ogni campo <code class=\"docutils literal notranslate\">foo</code>. Ti devi assicurare che questa registrazione avvenga prima che cerchi di creare un qualunque queryset che la usi. Puoi mettere l’implementazione in un file <code class=\"docutils literal notranslate\">models.py</code> , o registrare il criterio di ricerca nel metodo <code class=\"docutils literal notranslate\">ready()</code> di un <code class=\"docutils literal notranslate\">AppConfig</code>.</p>\n<p>Dando un’occhiata più attenta all’implementazione, il primo attributo richiesto é <code class=\"docutils literal notranslate\">lookup_name</code>. Questo permette alla ORM di capire come interpretare <code class=\"docutils literal notranslate\">name__ne</code> e usare <code class=\"docutils literal notranslate\">NotEqual</code> per generare il codice SQL. Per convenzione, questi nomi sono sempre stringhe in minuscolo contenenti solo lettere, ma l’unico requisito mandatorio è che non contengano la stringa <code class=\"docutils literal notranslate\">__</code>.</p>\n<p>Poi dobbiamo definire il metodo <code class=\"docutils literal notranslate\">as_sql</code> . Questo usa un oggetto <code class=\"docutils literal notranslate\">SQLCompiler</code> , chiamato <code class=\"docutils literal notranslate\">compiler</code>,  e la connessione al database attivo. Gli oggetti <code class=\"docutils literal notranslate\">SQLCompiler</code> non sono documentati, ma la sola cosa che dobbiamo sapere a loro riguardo è che hanno un metodo <code class=\"docutils literal notranslate\">compile()</code> che restituisce una tupla contenente una stringa SQL, e i parametri da interpolare in quella stringa. Nella maggior parte dei casi, non hai necessità di usarli direttamente e puoi passarli a <code class=\"docutils literal notranslate\">process_lhs()</code> e <code class=\"docutils literal notranslate\">process_rhs()</code>.</p>\n<p>Un <code class=\"docutils literal notranslate\">Lookup</code> lavora verso due valori, <code class=\"docutils literal notranslate\">lhs</code> e <code class=\"docutils literal notranslate\">rhs</code>, che rappresentano la parte sinistra e la parte destra. La parte sinistra di solito è un riferimento a un campo, ma può essere qualunque cosa implementi una <a class=\"reference internal\" href=\"/it/4.0/ref/models/lookups/#query-expression\"><span class=\"std std-ref\">query expression API</span></a>. La parte destra è il valore dato dall’utente. Nell’esempio <code class=\"docutils literal notranslate\">Author.objects.filter(name__ne='Jack')</code>, la parte sinistra è un riferimento al campo <code class=\"docutils literal notranslate\">name</code> del modello <code class=\"docutils literal notranslate\">Author</code> , e <code class=\"docutils literal notranslate\">'Jack'</code> è la parte destra.</p>\n<p>Chiamiamo <code class=\"docutils literal notranslate\">process_lhs</code> e <code class=\"docutils literal notranslate\">process_rhs</code> per convertirli nei valori che ci servono per il codice SQL usando l’oggetto <code class=\"docutils literal notranslate\">compiler</code> descritto in precedenza. Questi metodi ritornano tuple contenenti il codice SQL e i parametri che devono essere interpolati in quel codice SQL, esattamente come si devono essere restituiti dal nostro metodo <code class=\"docutils literal notranslate\">as_sql</code> . Nell’esempio precedente, <code class=\"docutils literal notranslate\">process_lhs</code> restituisce <code class=\"docutils literal notranslate\">('&quot;author&quot;.&quot;name&quot;', [])</code> e <code class=\"docutils literal notranslate\">process_rhs</code> restituisce <code class=\"docutils literal notranslate\">('&quot;%s&quot;', ['Jack'])</code>. In questo esempio non c’erano parametri per la parte sinistra, ma può dipendere dall’oggetto che abbiamo, per questo dobbiamo includerli nei parametri che restituiamo.</p>\n<p>Finalmente combiniamo le parti in una espressione SQL con <code class=\"docutils literal notranslate\">&lt;&gt;</code>, e riforniamo? con tutti i parametri per l’interrogazione. Dopodiché ritorniamo una tupla contenente la stringa SQL e i parametri generati.</p>\n</section>\n<section id=\"a-transformer-example\">\n<h2>Un esempio di trasformatore<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>La ricerca personalizzata sopra indicata è fantastica, ma in alcuni casi potresti aver bisogno di concatenare le ricerche insieme. Per esempio, supponiamo che stiamo costruendo la nostra applicazione laddove vogliamo fare uso del operatore <code class=\"docutils literal notranslate\">abs()</code>. Abbiamo un modello <code class=\"docutils literal notranslate\">Experiment</code> che registra un valore inizio, un valore fine, e che un valore cambio ( inizio - fine ). Ci piacerebe cercare tutti gli esperimenti dove valore cambio è uguale ad alcuni valori (<code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code>),o qualsiasi vaolore che non supera un certo quantitativo  (<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\">Nota</p>\n<p>Questo esempio è in qualche modo ?forzato?, ma ci mostra il range di funzionalita possibili nel database backend in maniera indipendete, e senza duplicare funzionalita gia esistenti in Django</p>\n</aside>\n<p>Cominceremo con la scrittura del convertitore``AbsoluteValue``. Utilizzeremo le funzioni SQL <code class=\"docutils literal notranslate\">ABS()</code> per convertire il valore prima del confronto:</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>Successivamente registriamolo per il campo <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>Adesso possiamo lanciare le query che avevamo prima. <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs=27)</code> genererà il seguente 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=\"p\">...</span> <span class=\"k\">WHERE</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=\"o\">=</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>Usare <code class=\"docutils literal notranslate\">Transform</code> invece di <code class=\"docutils literal notranslate\">Lookup</code> significa che saremo in grado di concatenare ulteriori lookup in seguito. Così <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> genererà il seguente 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=\"p\">...</span> <span class=\"k\">WHERE</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=\"o\">&lt;</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>Nel caso non ci siano altre ricerche specificate, Django interpreta <code class=\"docutils literal notranslate\">change__abs=27</code>  come <code class=\"docutils literal notranslate\">change__abs__exact=27</code>.</p>\n<p>Questo consente anche al risultato di essere usato in espressioni <code class=\"docutils literal notranslate\">ORDER BY</code> e <code class=\"docutils literal notranslate\">DISTINCT ON</code>. Per esempio <code class=\"docutils literal notranslate\">Experiment.objects.order_by('change__abs')</code> produce:</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=\"p\">...</span> <span class=\"k\">ORDER</span> <span class=\"k\">BY</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=\"k\">ASC</span>\n</code></pre></div>\n<p>E nei database che supportano distinct sui campi (come PostgreSQL), <code class=\"docutils literal notranslate\">Experiment.objects.distinct('change__abs')</code>  produce:</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=\"p\">...</span> <span class=\"k\">DISTINCT</span> <span class=\"k\">ON</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>Quando cerca quali lookup sono disponibili dopo avere applicato la <code class=\"docutils literal notranslate\">Transform</code>, Django usa l’attributo <code class=\"docutils literal notranslate\">output_field</code>. Se l’attributo non è cambiato, non abbiamo necessità di specificarlo, ma supponiamo che stavamo applicando la  <code class=\"docutils literal notranslate\">AbsoluteValue</code> ad un campo che rappresenta un tipo più complesso (per esempio un punto relativo ad una origine, o un numero complesso), allora per ulteriori lookup avremmo voluto specificare il fatto che la trasformazione ritorna un tipo <code class=\"docutils literal notranslate\">FloatField</code>. Ciò può essere fatto aggiungendo un attributo  <code class=\"docutils literal notranslate\">output_field</code> alla trasformazione:</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>Questo assicura che future ricerce come <code class=\"docutils literal notranslate\">abs__lte</code> si comportino come per <code class=\"docutils literal notranslate\">FloatField</code>.</p>\n</section>\n<section id=\"writing-an-efficient-abs-lt-lookup\">\n<h2>Scrivere una <code class=\"docutils literal notranslate\">abs__lt</code> ricerca efficiente<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>Usando il lookup <code class=\"docutils literal notranslate\">abs</code> di cui sopra, l’SQL che viene prodotto in qualche caso non utilizzerà gli indici prodotti efficientemente. In particolare, l’utilizzo di <code class=\"docutils literal notranslate\">change__abs__lt=27</code> è equivalente all’utilizzo di <code class=\"docutils literal notranslate\">change__gt=-27</code> AND <code class=\"docutils literal notranslate\">change__lt=27</code>. (Per il caso <code class=\"docutils literal notranslate\">lte</code> avremmo potuto usare il <code class=\"docutils literal notranslate\">BETWEEN</code> di SQL).</p>\n<p>Ci piacerebbe che <code class=\"docutils literal notranslate\">Experiment.objects.filter(change__abs__lt=27)</code> generi la seguente 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=\"p\">..</span> <span class=\"k\">WHERE</span> <span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span> <span class=\"o\">&lt;</span> <span class=\"mi\">27</span> <span class=\"k\">AND</span> <span class=\"ss\">&quot;experiments&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;change&quot;</span> <span class=\"o\">&gt;</span> <span class=\"o\">-</span><span class=\"mi\">27</span>\n</code></pre></div>\n<p>L’implemetazione è:</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>Ci sono un paio di cose che accadono e che vale la pena di notare. La prima è che <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code> non sta chiamando <code class=\"docutils literal notranslate\">process_lhs()</code>. Piuttosto, salta la trasformazione di <code class=\"docutils literal notranslate\">lhs</code> fatta da <code class=\"docutils literal notranslate\">AbsoluteValue</code> e utilizza l” <code class=\"docutils literal notranslate\">lhs</code> originale. Cioè, vogliamo ottenere <code class=\"docutils literal notranslate\">&quot;experiments&quot;.&quot;change&quot;</code> e non <code class=\"docutils literal notranslate\">ABS(&quot;experiments&quot;.&quot;change&quot;)</code>. Fare riferimento direttamente a <code class=\"docutils literal notranslate\">self.lhs.lhs</code> è sicuro perchè <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code> può essere acceduto solo dal lookup <code class=\"docutils literal notranslate\">AbsoluteValue</code>, quindi <code class=\"docutils literal notranslate\">lhs</code> è sempre una istanza di <code class=\"docutils literal notranslate\">AbsoluteValue</code>.</p>\n<p>Nota anche che poichè entrambe le parti sono utilizzate più volte nella query, i parametri devono contenere <code class=\"docutils literal notranslate\">lhs_params</code> e <code class=\"docutils literal notranslate\">rhs_params</code> più volte.</p>\n<p>La query finale fà l’inversione (<code class=\"docutils literal notranslate\">27</code> a <code class=\"docutils literal notranslate\">-27</code>) direttamente nel database. La ragione per cui fà così è che se <code class=\"docutils literal notranslate\">self.rhs` non è un semplice valore intero (per esempio una ``F()</code> reference) non possiamo fare la trasformazione in Python.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Nota</p>\n<p>In effetti, molti lookup con <code class=\"docutils literal notranslate\">__abs</code> potrebbero essere implementati con delle query range come questa e su molti database di backend sarebbe anche più ragionevole, perchè potrebbero usare gli indici. In ogni caso con PostgreSQL potresti voler aggiungere un indice su <code class=\"docutils literal notranslate\">abs(change)</code> che permetterebbe a queste query di essere molto efficienti.</p>\n</aside>\n</section>\n<section id=\"a-bilateral-transformer-example\">\n<h2>Un esempio di trasformatore bilaterale<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>L’esempio <code class=\"docutils literal notranslate\">AbsoluteValue</code> che abbiamo discusso in precedenza è una trasformazione che si applica al lato sinistro della ricerca. Potrebbero esserci alcuni casi in cui si desidera applicare la trasformazione sia al lato sinistro che al lato destro. Ad esempio, se si desidera filtrare un set di query in base all’uguaglianza del lato sinistro e destro in modo insensibile ad alcune funzioni SQL.</p>\n<p>Esaminiamo qui le trasformazioni senza distinzione tra maiuscole e minuscole. Questa trasformazione non è molto utile in pratica poiché Django viene già fornito con una serie di ricerche integrate senza distinzione tra maiuscole e minuscole, ma sarà una bella dimostrazione di trasformazioni bilaterali in modo indipendente dal database.</p>\n<p>Definiamo un trasformatore <code class=\"docutils literal notranslate\">Maiuscolo</code> che utilizza la funzione SQL <code class=\"docutils literal notranslate\">UPPER()</code> per trasformare i valori prima del confronto. Definiamo <a class=\"reference internal\" href=\"/it/4.0/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> per indicare che questa trasformazione dovrebbe applicarsi sia a <code class=\"docutils literal notranslate\">lhs</code> che a <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>Successivamente registriamolo:</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>Ora, il queryset <code class=\"docutils literal notranslate\">Author.objects.filter(name__upper=&quot;doe&quot;)</code> genererà una query senza distinzione tra maiuscole e minuscole come questa:</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=\"p\">...</span> <span class=\"k\">WHERE</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=\"o\">=</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>Scrivendo implementazioni alternative per le ricerche esistenti<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>A volte database vendor differenti richiedono SQL diverso per le stesse operazioni.  Per questo esempio, riscriveremo una implementazione custom dell’operatore NotEqual per MySQL. Invece di <code class=\"docutils literal notranslate\">&lt;&gt;</code> useremo l’operatore <code class=\"docutils literal notranslate\">!=</code>. (Nota che in realtà praticamente tutti i database li supportano entrambi, inclusi quelli supportati da Django).</p>\n<p>Puoi cambiare il comportamento di uno specifico backend creando una sottoclasse di «NotEqual» con un metodo «as_mysql»</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>Poi possiamo registrarlo con <code class=\"docutils literal notranslate\">Field</code>. Prende il posto della classe <code class=\"docutils literal notranslate\">NotEqual</code> originale dal momento che ha lo stesso <code class=\"docutils literal notranslate\">lookup_name</code>.</p>\n<p>Quando compila una query, Django prima cerca i metodi <code class=\"docutils literal notranslate\">as_%s % connection.vendor</code> e poi ricade su <code class=\"docutils literal notranslate\">as_sql</code>. I nomi dei vendor per i backends built-in sono <code class=\"docutils literal notranslate\">sqlite</code>, <code class=\"docutils literal notranslate\">postgresql</code>, <code class=\"docutils literal notranslate\">oracle</code> e <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>Come Django determina le ricerche e trasforma quelle in uso<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 alcuni casi potresti voler cambiare dinamicamente quale <code class=\"docutils literal notranslate\">Transform</code> o <code class=\"docutils literal notranslate\">Lookup</code> viene restituito a seconda del nome che gli passi, piuttosto che metterlo a posto. Per esempio, potresti avere un campo che contiene coordinate di una dimensione arbitraria e vorresti poter consentire una sintassi di tipo <code class=\"docutils literal notranslate\">.filter(coords__x7=4)</code> per restituire gli oggetti in cui la settima coordinata vale 4. Per fare questo, faresti override di <code class=\"docutils literal notranslate\">get_lookup</code> con qualcosa come:</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>Poi definiresti in modo appropriato <code class=\"docutils literal notranslate\">get_coordinate_lookup</code> per restituire una sottoclasse di <code class=\"docutils literal notranslate\">Lookup</code> che gestisce la dimensione rilevante di <code class=\"docutils literal notranslate\">dimension</code>.</p>\n<p>Esiste un metodo che è chiamato <code class=\"docutils literal notranslate\">get_transform()</code>, in modo simile. <code class=\"docutils literal notranslate\">get_lookup()</code> dovrebbe sempre restituire una sottoclasse <code class=\"docutils literal notranslate\">Lookup</code> e <code class=\"docutils literal notranslate\">get_transform()</code> una sottoclasse <code class=\"docutils literal notranslate\">Transform</code>. E” importante ricordare che gli oggetti <code class=\"docutils literal notranslate\">Transform</code> possono essere ulteriormente filtrati, cosa che non possibile fare per gli oggetti <code class=\"docutils literal notranslate\">Lookup</code>.</p>\n<p>In fase di filtering, se rimane un solo lookup name da risolvere, cercheremo un <code class=\"docutils literal notranslate\">Lookup</code>. Se ci sono più nomi, si cercherà per un <code class=\"docutils literal notranslate\">Transform</code>. Nella situazione in cui ci sia solo un nome e non si trovi un <code class=\"docutils literal notranslate\">Lookup</code>, cercheremo un <code class=\"docutils literal notranslate\">Transform</code> e poi il lookup <code class=\"docutils literal notranslate\">exact</code> su quel <code class=\"docutils literal notranslate\">Transform</code>. Tutte le sequenze di chiamate terminano sempre con un <code class=\"docutils literal notranslate\">Lookup</code>. Per fare chiarezza:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mylookup)</code> chiamera <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> chimaerà <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code>, e poi <code class=\"docutils literal notranslate\">mytransform.get_lookup('mylookup')</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mytransform)</code> chiamerà prima <code class=\"docutils literal notranslate\">myfield.get_lookup('mytransform')</code>, che fallirà, così farà fallback su <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code> e poi <code class=\"docutils literal notranslate\">mytransform.get_lookup('exact')</code>.</p></li>\n</ul>\n</section>","rootId":"how-to-write-custom-lookups","toc":[{"title":"Un esempio di criterio di ricerca","anchor":"a-lookup-example","children":[]},{"title":"Un esempio di trasformatore","anchor":"a-transformer-example","children":[]},{"title":"Scrivere una abs__lt ricerca efficiente","anchor":"writing-an-efficient-abs-lt-lookup","children":[]},{"title":"Un esempio di trasformatore bilaterale","anchor":"a-bilateral-transformer-example","children":[]},{"title":"Scrivendo implementazioni alternative per le ricerche esistenti","anchor":"writing-alternative-implementations-for-existing-lookups","children":[]},{"title":"Come Django determina le ricerche e trasforma quelle in uso","anchor":"how-django-determines-the-lookups-and-transforms-which-are-used","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"«How-to» guides","url":"/it/4.0/howto/"}],"prev":{"docname":"howto/custom-model-fields","title":"Come creare model field personalizzati","url":"/it/4.0/howto/custom-model-fields/"},"next":{"docname":"howto/custom-template-backend","title":"Come implementare un backend per template personalizzato","url":"/it/4.0/howto/custom-template-backend/"},"formats":{"html":"/it/4.0/howto/custom-lookups/","markdown":"/it/4.0/howto/custom-lookups.md","json":"/it/4.0/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/4.0.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/it/4.0/howto/custom-lookups/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}