{"title":"Come scrivere lookup personalizzati","version":"6.1","locale":"it","docname":"howto/custom-lookups","url":"/it/6.1/howto/custom-lookups/","canonical":"https://djangodocs.dev/it/6.1/howto/custom-lookups/","summary":"Django offre una ampia varietà di built-in lookups per la selezione (per esempio, exact e icontains ). Questo documento spiega come scrivere criteri di ricerca…","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/6.1/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\"><span class=\"pre\">exact</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">icontains</span></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/6.1/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\"><span class=\"pre\">ne</span></code> che lavora in modo opposto ad <code class=\"docutils literal notranslate\"><span class=\"pre\">exact</span></code>. <code class=\"docutils literal notranslate\"><span class=\"pre\">Author.objects.filter(name__ne='Jack')</span></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=\"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>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=\"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>Per registrare il lookup <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> dovremo chiamare <code class=\"docutils literal notranslate\"><span class=\"pre\">register_lookup</span></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\"><span class=\"pre\">Field</span></code>, così possiamo registrarlo direttamente con <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>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=\"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>Adesso possiamo usare <code class=\"docutils literal notranslate\"><span class=\"pre\">foo__ne</span></code> per ogni campo <code class=\"docutils literal notranslate\"><span class=\"pre\">foo</span></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\"><span class=\"pre\">models.py</span></code> , o registrare il criterio di ricerca nel metodo <code class=\"docutils literal notranslate\"><span class=\"pre\">ready()</span></code> di un <code class=\"docutils literal notranslate\"><span class=\"pre\">AppConfig</span></code>.</p>\n<p>Dando un’occhiata più attenta all’implementazione, il primo attributo richiesto é <code class=\"docutils literal notranslate\"><span class=\"pre\">lookup_name</span></code>. Questo permette alla ORM di capire come interpretare <code class=\"docutils literal notranslate\"><span class=\"pre\">name__ne</span></code> e usare <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></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\"><span class=\"pre\">__</span></code>.</p>\n<p>We then need to define the <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql</span></code> method. This takes a <code class=\"docutils literal notranslate\"><span class=\"pre\">SQLCompiler</span></code>\nobject, called <code class=\"docutils literal notranslate\"><span class=\"pre\">compiler</span></code>, and the active database connection.\n<code class=\"docutils literal notranslate\"><span class=\"pre\">SQLCompiler</span></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\"><span class=\"pre\">compile()</span></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\"><span class=\"pre\">process_lhs()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs()</span></code>.</p>\n<p>Un <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> lavora verso due valori, <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs</span></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/6.1/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\"><span class=\"pre\">Author.objects.filter(name__ne='Jack')</span></code>, la parte sinistra è un riferimento al campo <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> del modello <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> , e <code class=\"docutils literal notranslate\"><span class=\"pre\">'Jack'</span></code> è la parte destra.</p>\n<p>Chiamiamo <code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs</span></code> per convertirli nei valori che ci servono per il codice SQL usando l’oggetto <code class=\"docutils literal notranslate\"><span class=\"pre\">compiler</span></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\"><span class=\"pre\">as_sql</span></code> . Nell’esempio precedente, <code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs</span></code> restituisce <code class=\"docutils literal notranslate\"><span class=\"pre\">('&quot;author&quot;.&quot;name&quot;',</span> <span class=\"pre\">[])</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs</span></code> restituisce <code class=\"docutils literal notranslate\"><span class=\"pre\">('&quot;%s&quot;',</span> <span class=\"pre\">['Jack'])</span></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\"><span class=\"pre\">&lt;&gt;</span></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\"><span class=\"pre\">abs()</span></code>. Abbiamo un modello <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment</span></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\"><span class=\"pre\">Experiment.objects.filter(change__abs=27)</span></code>),o qualsiasi vaolore che non supera un certo quantitativo  (<code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></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\"><span class=\"pre\">ABS()</span></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=\"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>Successivamente registriamolo per il campo <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>Adesso possiamo lanciare le query che avevamo prima. <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs=27)</span></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=\"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>Usare <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> invece di <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> significa che saremo in grado di concatenare ulteriori lookup in seguito. Così <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></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=\"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>Nel caso non ci siano altre ricerche specificate, Django interpreta <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs=27</span></code>  come <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs__exact=27</span></code>.</p>\n<p>Questo consente anche al risultato di essere usato in espressioni <code class=\"docutils literal notranslate\"><span class=\"pre\">ORDER</span> <span class=\"pre\">BY</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">DISTINCT</span> <span class=\"pre\">ON</span></code>. Per esempio <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.order_by('change__abs')</span></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=\"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>E nei database che supportano distinct sui campi (come PostgreSQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.distinct('change__abs')</span></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=\"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>Quando cerca quali lookup sono disponibili dopo avere applicato la <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>, Django usa l’attributo <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code>. Se l’attributo non è cambiato, non abbiamo necessità di specificarlo, ma supponiamo che stavamo applicando la  <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></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\"><span class=\"pre\">FloatField</span></code>. Ciò può essere fatto aggiungendo un attributo  <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></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=\"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>Questo assicura che future ricerce come <code class=\"docutils literal notranslate\"><span class=\"pre\">abs__lte</span></code> si comportino come per <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>Scrivere una <code class=\"docutils literal notranslate\"><span class=\"pre\">abs__lt</span></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\"><span class=\"pre\">abs</span></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\"><span class=\"pre\">change__abs__lt=27</span></code> è equivalente all’utilizzo di <code class=\"docutils literal notranslate\"><span class=\"pre\">change__gt=-27</span></code> AND <code class=\"docutils literal notranslate\"><span class=\"pre\">change__lt=27</span></code>. (Per il caso <code class=\"docutils literal notranslate\"><span class=\"pre\">lte</span></code> avremmo potuto usare il <code class=\"docutils literal notranslate\"><span class=\"pre\">BETWEEN</span></code> di SQL).</p>\n<p>Ci piacerebbe che <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></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=\"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>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=\"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>Ci sono un paio di cose che accadono e che vale la pena di notare. La prima è che <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValueLessThan</span></code> non sta chiamando <code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs()</span></code>. Piuttosto, salta la trasformazione di <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> fatta da <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> e utilizza l” <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> originale. Cioè, vogliamo ottenere <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;experiments&quot;.&quot;change&quot;</span></code> e non <code class=\"docutils literal notranslate\"><span class=\"pre\">ABS(&quot;experiments&quot;.&quot;change&quot;)</span></code>. Fare riferimento direttamente a <code class=\"docutils literal notranslate\"><span class=\"pre\">self.lhs.lhs</span></code> è sicuro perchè <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValueLessThan</span></code> può essere acceduto solo dal lookup <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code>, quindi <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> è sempre una istanza di <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></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\"><span class=\"pre\">lhs_params</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs_params</span></code> più volte.</p>\n<p>La query finale fà l’inversione (<code class=\"docutils literal notranslate\"><span class=\"pre\">27</span></code> a <code class=\"docutils literal notranslate\"><span class=\"pre\">-27</span></code>) direttamente nel database. La ragione per cui fà così è che se <code class=\"docutils literal notranslate\"><span class=\"pre\">self.rhs`</span> <span class=\"pre\">non</span> <span class=\"pre\">è</span> <span class=\"pre\">un</span> <span class=\"pre\">semplice</span> <span class=\"pre\">valore</span> <span class=\"pre\">intero</span> <span class=\"pre\">(per</span> <span class=\"pre\">esempio</span> <span class=\"pre\">una</span> <span class=\"pre\">``F()</span></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\"><span class=\"pre\">__abs</span></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\"><span class=\"pre\">abs(change)</span></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\"><span class=\"pre\">AbsoluteValue</span></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\"><span class=\"pre\">Maiuscolo</span></code> che utilizza la funzione SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">UPPER()</span></code> per trasformare i valori prima del confronto. Definiamo <a class=\"reference internal\" href=\"/it/6.1/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> per indicare che questa trasformazione dovrebbe applicarsi sia a <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> che a <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>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=\"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>Ora, il queryset <code class=\"docutils literal notranslate\"><span class=\"pre\">Author.objects.filter(name__upper=&quot;doe&quot;)</span></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=\"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>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\"><span class=\"pre\">&lt;&gt;</span></code> useremo l’operatore <code class=\"docutils literal notranslate\"><span class=\"pre\">!=</span></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=\"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>Poi possiamo registrarlo con <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>. Prende il posto della classe <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> originale dal momento che ha lo stesso <code class=\"docutils literal notranslate\"><span class=\"pre\">lookup_name</span></code>.</p>\n<p>Quando compila una query, Django prima cerca i metodi <code class=\"docutils literal notranslate\"><span class=\"pre\">as_%s</span> <span class=\"pre\">%</span> <span class=\"pre\">connection.vendor</span></code> e poi ricade su <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql</span></code>. I nomi dei vendor per i backends built-in sono <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> e <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>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\"><span class=\"pre\">Transform</span></code> o <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></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\"><span class=\"pre\">.filter(coords__x7=4)</span></code> per restituire gli oggetti in cui la settima coordinata vale 4. Per fare questo, faresti override di <code class=\"docutils literal notranslate\"><span class=\"pre\">get_lookup</span></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=\"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>Poi definiresti in modo appropriato <code class=\"docutils literal notranslate\"><span class=\"pre\">get_coordinate_lookup</span></code> per restituire una sottoclasse di <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> che gestisce la dimensione rilevante di <code class=\"docutils literal notranslate\"><span class=\"pre\">dimension</span></code>.</p>\n<p>Esiste un metodo che è chiamato <code class=\"docutils literal notranslate\"><span class=\"pre\">get_transform()</span></code>, in modo simile. <code class=\"docutils literal notranslate\"><span class=\"pre\">get_lookup()</span></code> dovrebbe sempre restituire una sottoclasse <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">get_transform()</span></code> una sottoclasse <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>. E” importante ricordare che gli oggetti <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> possono essere ulteriormente filtrati, cosa che non possibile fare per gli oggetti <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code>.</p>\n<p>In fase di filtering, se rimane un solo lookup name da risolvere, cercheremo un <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code>. Se ci sono più nomi, si cercherà per un <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>. Nella situazione in cui ci sia solo un nome e non si trovi un <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code>, cercheremo un <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> e poi il lookup <code class=\"docutils literal notranslate\"><span class=\"pre\">exact</span></code> su quel <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>. Tutte le sequenze di chiamate terminano sempre con un <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code>. Per fare chiarezza:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(myfield__mylookup)</span></code> chiamera <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> chimaerà <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_transform('mytransform')</span></code>, e poi <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> chiamerà prima <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_lookup('mytransform')</span></code>, che fallirà, così farà fallback su <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_transform('mytransform')</span></code> e poi <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":"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/6.1/howto/"}],"prev":{"docname":"howto/writing-migrations","title":"Come creare migrazioni di database","url":"/it/6.1/howto/writing-migrations/"},"next":{"docname":"howto/outputting-csv","title":"Come creare un output su CSV","url":"/it/6.1/howto/outputting-csv/"},"formats":{"html":"/it/6.1/howto/custom-lookups/","markdown":"/it/6.1/howto/custom-lookups.md","json":"/it/6.1/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/it/6.1/howto/custom-lookups/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}