{"title":"Como escrever pesquisadores customizadas","version":"6.0","locale":"pt-br","docname":"howto/custom-lookups","url":"/pt-br/6.0/howto/custom-lookups/","canonical":"https://djangodocs.dev/pt-br/6.0/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>Como escrever pesquisadores customizadas<a class=\"heading-anchor\" href=\"#how-to-write-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\"><span class=\"pre\">exact</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">icontains</span></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-lookup-example\">\n<h2>Um exemplo de filtro<a class=\"heading-anchor\" href=\"#a-lookup-example\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Vamos começar com um pequeno pesquisador customizado. Nós iremos escrever um pesquisador customizado <code class=\"docutils literal notranslate\"><span class=\"pre\">ne</span></code> que irá funcionar de maneira contrária ao <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> irá ser traduzido para o 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>Este SQL é independente, por isso, não precisa se preocupar com os bancos de dados diferentes.</p>\n<p>Há dois passos para fazer isso funcionar. Primeiramente nós precisamos implementar o filtro, então precisamos informar ao Django sobre isso:</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>Para registrar o pesquisador <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> vamos precisar chamar <code class=\"docutils literal notranslate\"><span class=\"pre\">register_lookup</span></code> na classe de campo que queremos que o pesquisador esteja disponível. Nesse caso, o pesquisador faz sentido para todas as subclasses de <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>, então vamos registrá-lo diretamente com <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>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=\"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>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\"><span class=\"pre\">ready()</span></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\"><span class=\"pre\">as_sql</span></code>. Este recebe um objeto <code class=\"docutils literal notranslate\"><span class=\"pre\">SQL</span> <span class=\"pre\">Compiler</span></code>, chamado <code class=\"docutils literal notranslate\"><span class=\"pre\">compiler</span></code>, e a conexão de banco de dados ativa. Os objetos <code class=\"docutils literal notranslate\"><span class=\"pre\">SQLCompiler</span></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\"><span class=\"pre\">compile()</span></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\"><span class=\"pre\">process_lhs()</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">process_rhs()</span></code>.</p>\n<p>A <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> trabalha em dois valores, e <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs</span></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/6.0/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\"><span class=\"pre\">Author.objects.filter</span> <span class=\"pre\">(name__ne</span> <span class=\"pre\">=</span> <span class=\"pre\">'Jack')</span></code>, o lado esquerdo é uma referência para o campo <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> campo do modelo <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code>, e <code class=\"docutils literal notranslate\"><span class=\"pre\">'Jack</span> <span class=\"pre\">'</span></code> é o lado direito.</p>\n<p>Nós chamamos <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> para convertê-los para os valores que precisamos para SQL usando o objeto <code class=\"docutils literal notranslate\"><span class=\"pre\">compiler</span></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\"><span class=\"pre\">as_sql</span></code>. No exemplo acima, <code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs</span></code> retorna <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> retorna <code class=\"docutils literal notranslate\"><span class=\"pre\">('&quot;%s&quot;',</span> <span class=\"pre\">[</span> <span class=\"pre\">'Jack'</span> <span class=\"pre\">])</span></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\"><span class=\"pre\">&lt;&gt;</span></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-transformer-example\">\n<h2>Um exemplo de transformador<a class=\"heading-anchor\" href=\"#a-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\"><span class=\"pre\">abs()</span></code>. Temos um modelo <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment</span></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\"><span class=\"pre\">Experiment.objects.filter</span> <span class=\"pre\">(change__abs</span> <span class=\"pre\">=</span> <span class=\"pre\">27)</span></code>), ou onde não exceda um certo montante ( <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter</span> <span class=\"pre\">(change__abs__lt</span> <span class=\"pre\">=</span> <span class=\"pre\">27)</span></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\"><span class=\"pre\">AbsoluteValue</span></code>. Isso vai usar a função SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">ABS()</span></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=\"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>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=\"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>Agora nós podemos rodar as consultas que tínhamos antes. <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs=27)</span></code> irá gerar o seguinte 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>Ao usar <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> em vez de <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> somos capazes de usar outros pesquisadores em combinação depois. <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></code> irá gerar o seguinte 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>Note que no caso de não haver nenhuma outra lookup especificada, o Django interpreta <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs</span> <span class=\"pre\">=</span> <span class=\"pre\">27</span></code> como <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs__exact</span> <span class=\"pre\">=</span> <span class=\"pre\">27</span></code>.</p>\n<p>Isso também permite que o resultado seja usado nas clausálas <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>. Por exemplo <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.order_by('change__abs')</span></code> gera:</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 em bancos de dados que tem suporte ao distinct em campos (como o PostgreSQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.distinct('change__abs')</span></code> gera:</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>Ao procurar quais lookups são permitidas depois de aplicar o <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>, o Django usa o atributo <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code>. Não precisamos especificar isso aqui, já que não mudou, mas supondo que estivéssemos aplicando <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></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\"><span class=\"pre\">transform</span></code> retorne um tipo <code class=\"docutils literal notranslate\"><span class=\"pre\">FloatField</span></code> para os próximos lookups. Isso pode ser feito adicionando um atributo <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></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=\"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>Isso garante que novos filtros como o <code class=\"docutils literal notranslate\"><span class=\"pre\">abs__lte</span></code> se comportem como deveriam para um <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>Escrevendo um filtro <code class=\"docutils literal notranslate\"><span class=\"pre\">abs__lt</span></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\"><span class=\"pre\">abs</span></code> escrito acima, em alguns casos o SQL gerado não irá usar os índices de maneira eficiente. Em particular, quando usamos <code class=\"docutils literal notranslate\"><span class=\"pre\">change__abs__lt=27</span></code>, isso é equivalente a <code class=\"docutils literal notranslate\"><span class=\"pre\">change__gt=-27</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">change__lt=27</span></code>. (Para o caso <code class=\"docutils literal notranslate\"><span class=\"pre\">lte</span></code> podemos usar o <code class=\"docutils literal notranslate\"><span class=\"pre\">BETWEEN</span></code> do SQL).</p>\n<p>Então optaríamos por <code class=\"docutils literal notranslate\"><span class=\"pre\">Experiment.objects.filter(change__abs__lt=27)</span></code> para gerar o seguinte 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>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=\"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>Há algumas coisas notáveis ​​acontecendo. Em primeiro lugar, <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValueLessThan</span></code> não está chamando <code class=\"docutils literal notranslate\"><span class=\"pre\">process_lhs</span> <span class=\"pre\">()</span></code>. Em vez disso ele ignora a transformação do <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> feito por <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code> e usa o <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> original. Ou seja, queremos pegar `` “experiments”.”change” `` não <code class=\"docutils literal notranslate\"><span class=\"pre\">ABS(</span> <span class=\"pre\">&quot;experiments&quot;.</span> <span class=\"pre\">&quot;change&quot;)</span> <span class=\"pre\">``.</span> <span class=\"pre\">Referindo-se</span> <span class=\"pre\">diretamente</span> <span class=\"pre\">ao</span> <span class=\"pre\">``self.lhs.lhs</span></code> é tão seguro quanto o <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValueLessThan</span></code> pode ser acessado diretamente do filtro <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></code>, que é <code class=\"docutils literal notranslate\"><span class=\"pre\">lhs</span></code> é sempre uma instância de <code class=\"docutils literal notranslate\"><span class=\"pre\">AbsoluteValue</span></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\"><span class=\"pre\">lhs_params</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">rhs_params</span></code> várias vezes.</p>\n<p>A consulta final faz a inversão ( <code class=\"docutils literal notranslate\"><span class=\"pre\">27</span></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\"><span class=\"pre\">F()</span></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\"><span class=\"pre\">__abs</span></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\"><span class=\"pre\">abs(change)</span></code> o que 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\"><span class=\"pre\">AbsoluteValue</span></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 insensivelmente para alguma função SQL.</p>\n<p>Vamos examinar transformações insensíveis a maiúsculas-minúsculas. Essa transformação não é muito útil na prática já que o Django já contém vários pesquisadores como esse built-in, mas é uma boa demonstração de transformações bilaterais agnóstica ao banco de dados.</p>\n<p>Definimos um “transformer” de <code class=\"docutils literal notranslate\"><span class=\"pre\">UpperCase</span></code> que usa a função <code class=\"docutils literal notranslate\"><span class=\"pre\">UPPER()</span></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\"><span class=\"pre\">lhs</span></code> e <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>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=\"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>Agora, a queryset <code class=\"docutils literal notranslate\"><span class=\"pre\">Author.objects.filter(name__upper=&quot;doe&quot;)</span></code> irá gerar uma consulta insensível a maiúsculas-minúsculas como essa:</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>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\"><span class=\"pre\">&lt;&gt;</span></code> usaremos o operador <code class=\"docutils literal notranslate\"><span class=\"pre\">!=</span></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\"><span class=\"pre\">NotEqual</span></code> com um método <code class=\"docutils literal notranslate\"><span class=\"pre\">as_mysql</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MySQLNotEqual</span><span class=\"p\">(</span><span class=\"n\">NotEqual</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">as_mysql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">extra_context</span><span class=\"p\">):</span>\n        <span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">lhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_lhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">rhs</span><span class=\"p\">,</span> <span class=\"n\">rhs_params</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">process_rhs</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">)</span>\n        <span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"n\">lhs_params</span> <span class=\"o\">+</span> <span class=\"n\">rhs_params</span>\n        <span class=\"k\">return</span> <span class=\"s2\">&quot;</span><span class=\"si\">%s</span><span class=\"s2\"> != </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">lhs</span><span class=\"p\">,</span> <span class=\"n\">rhs</span><span class=\"p\">),</span> <span class=\"n\">params</span>\n\n\n<span class=\"n\">Field</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">MySQLNotEqual</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Podemos então registrá-lo com <code class=\"docutils literal notranslate\"><span class=\"pre\">Field</span></code>. Ele toma o lugar da classe <code class=\"docutils literal notranslate\"><span class=\"pre\">NotEqual</span></code> original já que tem o mesmo <code class=\"docutils literal notranslate\"><span class=\"pre\">lookup_name</span></code>.</p>\n<p>Ao compilar uma consulta, o Django primeiro procura pelos métodos <code class=\"docutils literal notranslate\"><span class=\"pre\">as_%s</span> <span class=\"pre\">%</span> <span class=\"pre\">connection.vendor</span></code>, e depois para <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql</span></code>. Os nomes de fornecedores para os back-ends suportados são <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>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\"><span class=\"pre\">Transform</span></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\"><span class=\"pre\">.filter</span> <span class=\"pre\">(coords__x7=4)</span></code> para retornar os objetos onde a 7ª coordenada tem valor 4. Para fazer isso, substitua <code class=\"docutils literal notranslate\"><span class=\"pre\">get_lookup</span></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=\"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>Você deve então definir `` get_coordinate_lookup`` adequadamente para retornar uma subclasse de <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> a qual lida com o valor relevante da <code class=\"docutils literal notranslate\"><span class=\"pre\">dimension</span></code>.</p>\n<p>Existe um método de nome semelhante chamado <code class=\"docutils literal notranslate\"><span class=\"pre\">get_transform()</span> <span class=\"pre\">``.</span> <span class=\"pre\">``</span> <span class=\"pre\">Get_lookup</span> <span class=\"pre\">()</span> <span class=\"pre\">``</span> <span class=\"pre\">deve</span> <span class=\"pre\">sempre</span> <span class=\"pre\">retornar</span> <span class=\"pre\">uma</span> <span class=\"pre\">subclasse</span> <span class=\"pre\">de</span> <span class=\"pre\">``Lookup</span></code>, e <code class=\"docutils literal notranslate\"><span class=\"pre\">get_transform()</span></code> uma subclasse de  <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>. É importante lembrar que objetos do tipo <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> podem ainda ser filtrados, e objetos do tipo <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></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\"><span class=\"pre\">Lookup</span></code>. Se houver vários nomes, ele irá procurar por um <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>. Em uma situação onde há apenas um nome e um <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code> não é encontrado, procuramos por um <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code> e então o  filtro <code class=\"docutils literal notranslate\"><span class=\"pre\">exact</span></code> naquele <code class=\"docutils literal notranslate\"><span class=\"pre\">Transform</span></code>. Todas as sequências de chamadas sempre terminam com um <code class=\"docutils literal notranslate\"><span class=\"pre\">Lookup</span></code>. Para esclarecer:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(myfield__mylookup)</span></code> irá chamar myfield.get_lookup(‘mylookup’)`.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">.filter(myfield__mytransform__mylookup)</span></code> irá chamar <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_transform('mytransform')</span></code>, e  em seguida <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> irá chamar primeiro <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_lookup(</span> <span class=\"pre\">'mytransform')</span></code>, o qual irá falhar, por isso vai retornar e chamar <code class=\"docutils literal notranslate\"><span class=\"pre\">myfield.get_transform('mytransform')</span></code> e em seguida, <code class=\"docutils literal notranslate\"><span class=\"pre\">mytransform.get_lookup(</span> <span class=\"pre\">&quot;exact&quot;)</span></code>.</p></li>\n</ul>\n</section>","rootId":"how-to-write-custom-lookups","toc":[{"title":"Um exemplo de filtro","anchor":"a-lookup-example","children":[]},{"title":"Um exemplo de transformador","anchor":"a-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":"How-to guides","url":"/pt-br/6.0/howto/"}],"prev":{"docname":"howto/writing-migrations","title":"How to create database migrations","url":"/pt-br/6.0/howto/writing-migrations/"},"next":{"docname":"howto/outputting-csv","title":"How to create CSV output","url":"/pt-br/6.0/howto/outputting-csv/"},"formats":{"html":"/pt-br/6.0/howto/custom-lookups/","markdown":"/pt-br/6.0/howto/custom-lookups.md","json":"/pt-br/6.0/howto/custom-lookups.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/howto/custom-lookups.txt","official":"https://docs.djangoproject.com/pt-br/6.0/howto/custom-lookups/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}