{"title":"Pesquisas personalizadas","version":"2.1","locale":"pt-br","docname":"howto/custom-lookups","url":"/pt-br/2.1/howto/custom-lookups/","canonical":"https://djangodocs.dev/pt-br/2.1/howto/custom-lookups/","summary":"Django oferece uma grande variedade de: ref:lookups embutidas <field-lookups> para filtragem (por exemplo, exact e icontains ). Esta documentação explica como…","html":"<h1>Pesquisas personalizadas<a class=\"heading-anchor\" href=\"#custom-lookups\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django oferece uma grande variedade de: ref:lookups embutidas &lt;field-lookups&gt; para filtragem (por exemplo, <code class=\"docutils literal notranslate\">exact</code> e <code class=\"docutils literal notranslate\">icontains</code>). Esta documentação explica como escrever lookups personalizadas e como alterar o funcionamento de lookups existentes. Para as referências da API de lookups, consulte o: doc: /ref/models/lookups.</p>\n<section id=\"a-simple-lookup-example\">\n<h2>Um simples exemple de pesquisa<a class=\"heading-anchor\" href=\"#a-simple-lookup-example\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Vamos iniciar com uma simples pesquisa personalizada. Escreveremos uma simples pesquisa <code class=\"docutils literal notranslate\">ne</code> que funciona em frente ao <code class=\"docutils literal notranslate\">exato</code>. <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>Author.objects.filter(name__ne=’Jack’) traduzindo para 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>Este SQL é independente, por isso, não precisa se preocupar com os bancos de dados diferentes.</p>\n<p>Há duas etapas para fazer este trabalho. Em primeiro lugar precisamos implementar a filtro, e depois precisamos dizer ao Django sobre ele. A implementação é bastante simples</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>Para registrar o filtro <code class=\"docutils literal notranslate\">NotEqual</code> precisamos somente chamar <code class=\"docutils literal notranslate\">register_lookup</code> no campo da classe que queremos que o filtro esteja disponível. Neste caso, a lookup faz sentido em todos os  <code class=\"docutils literal notranslate\">Field</code> da sub-classe, então registramos isso com `` Field`` diretamente</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>O registro do filtro também pode ser feito usando um padrão de “decorator”:</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>Agora podemos usar `` foo__ne`` para qualquer campo `` foo``. Tenha certeza de registrar antes de tentar criar qualquer “querysets” que o use. É possível colocar a implementação no `` models.py``, ou registar a lookup no método <code class=\"docutils literal notranslate\">ready()</code> do `` AppConfig``.</p>\n<p>Olhando mais perto da implementação, o primeiro atributo obrigatório é `` lookup_name``. Isso permite que o ORM entenda como interpretar `` name__ne`` e use `` NotEqual`` para gerar o SQL. Por convenção, estes nomes são sempre em strings caixa baixa contendo apenas letras, mas a única exigência é que não contenha a string `` __``.</p>\n<p>Quando então é necessário definir o método <code class=\"docutils literal notranslate\">as_sql</code>. Este recebe um objeto <code class=\"docutils literal notranslate\">SQL Compiler</code>, chamado <code class=\"docutils literal notranslate\">compiler</code>, e a conexão de banco de dados ativa. Os objetos <code class=\"docutils literal notranslate\">SQLCompiler</code> não são documentados, mas a única coisa que precisamos saber sobre eles é que eles tem um método <code class=\"docutils literal notranslate\">compile()</code> o qual retorna uma tupla contendo uma string SQL, e os parâmetros a serem interpolados naquela string. Na maioria dos casos você não precisa usá-lo diretamente e pode ser passá-lo para o <code class=\"docutils literal notranslate\">process_lhs()</code> e <code class=\"docutils literal notranslate\">process_rhs()</code>.</p>\n<p>A <code class=\"docutils literal notranslate\">Lookup</code> trabalha em dois valores, e <code class=\"docutils literal notranslate\">lhs</code> e <code class=\"docutils literal notranslate\">rhs</code>, entendendo como left-hand side e right-hand side. O lado esquerdo é geralmente uma referência de campo, mas pode ser qualquer coisa que implemente <a class=\"reference internal\" href=\"/pt-br/2.1/ref/models/lookups/#query-expression\"><span class=\"std std-ref\">query expression API</span></a>. O lado direito é o valor dado pelo usuário. No exemplo <code class=\"docutils literal notranslate\">Author.objects.filter (name__ne = 'Jack')</code>, o lado esquerdo é uma referência para o campo <code class=\"docutils literal notranslate\">name</code> campo do modelo <code class=\"docutils literal notranslate\">Author</code>, e <code class=\"docutils literal notranslate\">'Jack '</code> é o lado direito.</p>\n<p>Nós chamamos <code class=\"docutils literal notranslate\">process_lhs</code> e <code class=\"docutils literal notranslate\">process_rhs</code> para convertê-los para os valores que precisamos para SQL usando o objeto <code class=\"docutils literal notranslate\">compiler</code> descrito antes. Esses métodos retornam tuplas contendo alguns comandos SQL e os parâmetros a serem interpolados dentro destes comandos SQL, assim como nós precisamos para retornar do nosso método <code class=\"docutils literal notranslate\">as_sql</code>. No exemplo acima, <code class=\"docutils literal notranslate\">process_lhs</code> retorna <code class=\"docutils literal notranslate\">('&quot;author&quot;.&quot;name&quot;', [])</code> e <code class=\"docutils literal notranslate\">process_rhs</code> retorna <code class=\"docutils literal notranslate\">('&quot;%s&quot;', [ 'Jack' ])</code>. Neste exemplo não havia parâmetros para o lado esquerdo, mas isso depende do objeto que temos, portanto ainda precisamos incluí-los nos parâmetros que retornamos.</p>\n<p>FInalmente combinamos as partes em uma expressão SQL com <code class=\"docutils literal notranslate\">&lt;&gt;</code>, e fornecemos todos os parâmetros para a consulta. Então retornamos uma tupla contendo a string SQL gerada e os parâmetros.</p>\n</section>\n<section id=\"a-simple-transformer-example\">\n<h2>Um exemplo simples transformador<a class=\"heading-anchor\" href=\"#a-simple-transformer-example\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>O lookup personalizado acima é boa, mas em alguns casos você queira ser capaz de lookups encadeadas. Por exemplo, vamos supor que estamos construindo uma aplicação onde queremos fazer uso do operador <code class=\"docutils literal notranslate\">abs()</code>. Temos um modelo <code class=\"docutils literal notranslate\">Experiment</code> que registra um valor inicial, o valor final e a mudança (início - fim). Gostaríamos de encontrar todos os experimentos em que a alteração foi igual a uma certa quantidade ( <code class=\"docutils literal notranslate\">Experiment.objects.filter (change__abs = 27)</code>), ou onde não exceda um certo montante ( <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>Este exemplo é um pouco artificial, mas demonstra muito bem a gama de funcionalidades que é possível de uma maneira independente em um backend de banco de dados., e sem duplicar funcionalidades já existentes no Django.</p>\n</aside>\n<p>Nos vamos começar escrevendo um transformador <code class=\"docutils literal notranslate\">AbsoluteValue</code>. Isso vai usar a função SQL <code class=\"docutils literal notranslate\">ABS()</code> para transformar o valor antes da comparação</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>Em seguida, vamos registrá-lo para `` IntegerField``</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>agora podemos executar as queries que tínhamos antes. <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>Experiment.objects.filter (change__abs = 27) `` irá gerar o seguinte 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>Ao usar o <code class=\"docutils literal notranslate\">Transform</code> ao invés de <code class=\"docutils literal notranslate\">Lookup</code> significa que somos capazes de encadear lookups umas às outras. Então <code class=\"docutils literal notranslate\">Experiment.objects.filter (change__abs__lt = 27)</code> irá gerar o seguinte 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\">&lt;</span> <span class=\"mi\">27</span>\n</code></pre></div>\n<p>Note que no caso de não haver nenhuma outra lookup especificada, o Django interpreta <code class=\"docutils literal notranslate\">change__abs = 27</code> como <code class=\"docutils literal notranslate\">change__abs__exact = 27</code>.</p>\n<p>Isso também permite que os resultados sejam utilizados nas cláusulas <code class=\"docutils literal notranslate\">ORDER BY</code> e <code class=\"docutils literal notranslate\">DISTINCT ON</code>. Por exemplo <code class=\"docutils literal notranslate\">Experiment.objects.order_by('change__abs')</code> gerando:</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>E em bancos de dados que suportam campos distintos (tais como PostgreSQL). <code class=\"docutils literal notranslate\">Experiment.objects.distinct('change__abs')</code> gerando:</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>Ordenação e suporte distinto foram adicionados tal como descrito nos dois últimos parágrafos.</p>\n</aside>\n<p>Ao procurar quais lookups são permitidas depois de aplicar o <code class=\"docutils literal notranslate\">Transform</code>, o Django usa o atributo <code class=\"docutils literal notranslate\">output_field</code>. Não precisamos especificar isso aqui, já que não mudou, mas supondo que estivéssemos aplicando <code class=\"docutils literal notranslate\">AbsoluteValue</code> para algum campo que represente um tipo mais complexo (por exemplo um ponto relativo a uma origem ou um número complexo) então talvez querer especificar que o <code class=\"docutils literal notranslate\">transform</code> retorne um tipo <code class=\"docutils literal notranslate\">FloatField</code> para os próximos lookups. Isso pode ser feito adicionando um atributo <code class=\"docutils literal notranslate\">output_field</code> ao “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>Isso garante que novos filtros como o <code class=\"docutils literal notranslate\">abs__lte</code> se comportem como deveriam para um <code class=\"docutils literal notranslate\">FloatField</code>.</p>\n</section>\n<section id=\"writing-an-efficient-abs-lt-lookup\">\n<h2>Escrevendo um filtro <code class=\"docutils literal notranslate\">abs__lt</code> eficiente<a class=\"heading-anchor\" href=\"#writing-an-efficient-abs-lt-lookup\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Quando usar o filtro <code class=\"docutils literal notranslate\">abs</code> escrito acima, em alguns casos o SQL gerado não irá usar os índices  de maneira eficiente. Em particular, quando usa <code class=\"docutils literal notranslate\">change__abs__lt=27</code>, isso é equivalente a <code class=\"docutils literal notranslate\">change__gt=-27</code> e <code class=\"docutils literal notranslate\">change__lt=27</code>. (Para o caso <code class=\"docutils literal notranslate\">lte</code> podemos usar o <code class=\"docutils literal notranslate\">BETWEEN</code> do SQL).</p>\n<p>Então nós gostaríamos que o <code class=\"docutils literal notranslate\">Experiment.objects.filter (change__abs__lt=27)</code> gerasse o seguinte 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>A implementação é:</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>Há algumas coisas notáveis ​​acontecendo. Em primeiro lugar, <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code> não está chamando <code class=\"docutils literal notranslate\">process_lhs ()</code>. Em vez disso ele ignora a transformação do <code class=\"docutils literal notranslate\">lhs</code> feito por <code class=\"docutils literal notranslate\">AbsoluteValue</code> e usa o <code class=\"docutils literal notranslate\">lhs</code> original. Ou seja, queremos pegar `` “experiments”.”change” `` não <code class=\"docutils literal notranslate\">ABS( &quot;experiments&quot;. &quot;change&quot;) ``. Referindo-se diretamente ao ``self.lhs.lhs</code> é tão seguro quanto o <code class=\"docutils literal notranslate\">AbsoluteValueLessThan</code> pode ser acessado diretamente do filtro <code class=\"docutils literal notranslate\">AbsoluteValue</code>, que é <code class=\"docutils literal notranslate\">lhs</code> é sempre uma instância de <code class=\"docutils literal notranslate\">AbsoluteValue</code>.</p>\n<p>Note também que como ambos os lados são usados ​​várias vezes na consulta os parâmetros precisam conter <code class=\"docutils literal notranslate\">lhs_params</code> e <code class=\"docutils literal notranslate\">rhs_params</code> várias vezes.</p>\n<p>A consulta final faz a inversão ( <code class=\"docutils literal notranslate\">27</code> para `` -27``) diretamente no banco de dados. A razão para isso é que, se o `` self.rhs`` é algo mais do que um valor inteiro simples (por exemplo, uma referência <code class=\"docutils literal notranslate\">F()</code> ) não podemos fazer as transformações em Python.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Nota</p>\n<p>Na verdade, a maioria das filtros com <code class=\"docutils literal notranslate\">__abs</code> poderiam ser implementados como consultas de intervalos como esta, e na maioria dos “backends” de banco de dados, é provável que seja mais sensato fazê-lo já que podería fazer uso dos índices. No entanto, com PostgreSQL você pode querer adicionar um índice na <code class=\"docutils literal notranslate\">abs(change)</code> o qual permitiria que essas consultas fossem muito eficientes.</p>\n</aside>\n</section>\n<section id=\"a-bilateral-transformer-example\">\n<h2>Um exemplo bilateral de “transforme”<a class=\"heading-anchor\" href=\"#a-bilateral-transformer-example\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>O exemplo <code class=\"docutils literal notranslate\">AbsoluteValue</code> discutido anteriormente é uma transformação que se aplica para o lado esquerdo da lookup. Pode haver alguns casos onde você quer que a transformação seja aplicada tanto para o lado esquerdo quanto para o lado direito. Por exemplo, se você quiser filtrar um queryset com base em uma igualdade de lado esquerdo e direito inperseptível para alguma função SQL.</p>\n<p>Vamos examinar o exemplo simples de transformação “case-insensitive” aqui. Essa transformação não é muito útil na prática, já que o Django já vem com um monte de pesquisas de maiúsculas e minúsculas embutidas, mas será uma boa demonstração de transformações bilaterais de uma forma agnóstica ao banco de dados.</p>\n<p>Definimos um “transformer” de <code class=\"docutils literal notranslate\">UpperCase</code> que usa a função <code class=\"docutils literal notranslate\">UPPER()</code> do SQL para transformar os valores antes da comparação. Definimos :attr: bilateral = True &lt;django.db.models.Transform.bilateral&gt; para indicar que essa transformação deve ser aplicada a ambos <code class=\"docutils literal notranslate\">lhs</code> e <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>Em seguida, registre</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>Agora, o queryset <code class=\"docutils literal notranslate\">Author.objects.filter(name__upper = &quot;doe&quot;)</code> irá gerar uma query case-insensitive como esta:</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>Escrever implementações alternativas para filtros existentes<a class=\"heading-anchor\" href=\"#writing-alternative-implementations-for-existing-lookups\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Às vezes, diferentes fornecedores de banco de dados requerem diferentes SQL para a mesma operação. Para este exemplo, vamos reescrever uma implementação personalizada para o do operador NotEqual para o MySQL. Em vez de <code class=\"docutils literal notranslate\">&lt;&gt;</code> usaremos o operador <code class=\"docutils literal notranslate\">!=</code>. (Note que, na realidade, quase todos os bancos de dados suportam ambos, incluindo todas as bases de dados oficiais apoiadas pelo Django).</p>\n<p>Nós podemos mudar o comportamento em um backend específico criado pela subclasse de <code class=\"docutils literal notranslate\">NotEqual</code> com um método <code class=\"docutils literal notranslate\">as_mysql</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span> <span class=\"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>\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>Podemos então registrá-lo com <code class=\"docutils literal notranslate\">Field</code>. Ele toma o lugar da classe <code class=\"docutils literal notranslate\">NotEqual</code> original já que tem o mesmo <code class=\"docutils literal notranslate\">lookup_name</code>.</p>\n<p>Ao compilar uma consulta, o Django primeiro procura pelos métodos <code class=\"docutils literal notranslate\">as_%s % connection.vendor</code>, e depois para <code class=\"docutils literal notranslate\">as_sql</code>. Os nomes de fornecedores para os back-ends suportados são <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>Como o Django determina quais filtros e “transforms” são usados<a class=\"heading-anchor\" href=\"#how-django-determines-the-lookups-and-transforms-which-are-used\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Em alguns casos, talvez queira mudar dinamicamente qual <code class=\"docutils literal notranslate\">Transform</code> ou filtro é devolvido com base no nome passado, em vez de corrigí-lo. Como exemplo, você pode ter um campo o qual armazena coordenadas ou uma dimensão arbitrária, e deseja permitir uma sintaxe como <code class=\"docutils literal notranslate\">.filter (coords__x7=4)</code> para retornar os objetos onde a 7ª coordenada tem valor 4. Para fazer isso, substitua <code class=\"docutils literal notranslate\">get_lookup</code> com algo como:</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>Você deve então definir `` get_coordinate_lookup`` adequadamente para retornar uma subclasse de <code class=\"docutils literal notranslate\">Lookup</code> a qual lida com o valor relevante da <code class=\"docutils literal notranslate\">dimension</code>.</p>\n<p>Existe um método de nome semelhante chamado <code class=\"docutils literal notranslate\">get_transform() ``. `` Get_lookup () `` deve sempre retornar uma subclasse de ``Lookup</code>, e <code class=\"docutils literal notranslate\">get_transform()</code> uma subclasse de  <code class=\"docutils literal notranslate\">Transform</code>. É importante lembrar que objetos do tipo <code class=\"docutils literal notranslate\">Transform</code> podem ainda ser filtrados, e objetos do tipo <code class=\"docutils literal notranslate\">Lookup</code> não.</p>\n<p>Ao filtrar, se houver apenas um nome de filtro remanescente a ser resolvido, olhamos para um <code class=\"docutils literal notranslate\">Lookup</code>. Se houver vários nomes, ele irá procurar por um <code class=\"docutils literal notranslate\">Transform</code>. Em uma situação onde há apenas um nome e um <code class=\"docutils literal notranslate\">Lookup</code> não é encontrado, procuramos por um <code class=\"docutils literal notranslate\">Transform</code> e então o  filtro <code class=\"docutils literal notranslate\">exact</code> naquele <code class=\"docutils literal notranslate\">Transform</code>. Todas as sequências de chamadas sempre terminam com um <code class=\"docutils literal notranslate\">Lookup</code>. Para esclarecer:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mylookup)</code> irá chamar myfield.get_lookup(‘mylookup’)`.</p></li>\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mytransform__mylookup)</code> irá chamar <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code>, e  em seguida <code class=\"docutils literal notranslate\">mytransform.get_lookup('mylookup')</code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\">.filter(myfield__mytransform)</code> irá chamar primeiro <code class=\"docutils literal notranslate\">myfield.get_lookup( 'mytransform')</code>, o qual irá falhar, por isso vai retornar e chamar <code class=\"docutils literal notranslate\">myfield.get_transform('mytransform')</code> e em seguida, <code class=\"docutils literal notranslate\">mytransform.get_lookup( &quot;exact&quot;)</code>.</p></li>\n</ul>\n</section>","rootId":"custom-lookups","toc":[{"title":"Um simples exemple de pesquisa","anchor":"a-simple-lookup-example","children":[]},{"title":"Um exemplo simples transformador","anchor":"a-simple-transformer-example","children":[]},{"title":"Escrevendo um filtro abs__lt eficiente","anchor":"writing-an-efficient-abs-lt-lookup","children":[]},{"title":"Um exemplo bilateral de “transforme”","anchor":"a-bilateral-transformer-example","children":[]},{"title":"Escrever implementações alternativas para filtros existentes","anchor":"writing-alternative-implementations-for-existing-lookups","children":[]},{"title":"Como o Django determina quais filtros e “transforms” são usados","anchor":"how-django-determines-the-lookups-and-transforms-which-are-used","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"Guias de “como fazer”","url":"/pt-br/2.1/howto/"}],"prev":{"docname":"howto/custom-model-fields","title":"Escrevendo campos personalizados de modelos.","url":"/pt-br/2.1/howto/custom-model-fields/"},"next":{"docname":"howto/custom-template-tags","title":"“Template tags” e filtros customizados","url":"/pt-br/2.1/howto/custom-template-tags/"},"formats":{"html":"/pt-br/2.1/howto/custom-lookups/","markdown":"/pt-br/2.1/howto/custom-lookups.md","json":"/pt-br/2.1/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/pt-br/2.1/howto/custom-lookups/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}