As pesquisas em campo de texto no Django são cheias de opções. Por exemplo, você pode filtrar por uma texto que contém outra string, que é o caso do .filter(name__contains=[busca]). Esse lookup contains gera um SQL mais ou menos assim:
SELECT ... FROM minha_tabela WHERE name LIKE '%busca%';
Essa query vai retornar algum nome que tiver o Gab no meio. Para amplificar mais ainda o campo da pesquisa, podemos avisar o Django para ignorar as letras de maiúsculas e minúsculas. Para isso, utilizamos o __icontains no lugar. O que vai acontecer é que, no caso da pesquisa por 'Gab', o Django vai retorar qualquer nome que tiver GAB, gAB, GaB, gab, gaB, etc... Bem mais amplo. Geralmente usamos isso em funcionalidades de pesquisa.
Porém, o post de hoje trata-se do lookup __unaccent. O UNACCENT é uma extesnão do PostgreSQL que a gente pode extender no Django.
O problema
O __icontains resolve boa parte dos problemas, porém caso os dados tenham algum acento, que é bastante comum na língua portuguesa, o usuário deveria informar os acentos, para que o Django encontrasse os nomes.
Exemplo Prático:
Person.objects.filter(name__icontains='arao')
Buscando usuários com o nome Arão, meu usuário não digitou o acento -> ~ (til) na hora da pesquisa e, mesmo existindo registros que contém o nome arão, o Django retornou uma query vazia. Isso acontece porque o Django e o Python considera 'a' != 'ã'.
Solução
A gente, como desenvolvedor, não pode ficar dependendo do cenário perfeito, que é quando o usuário digita o nome correto, com todos as pontuações.
Felizmente, o PostgreSQL tem uma extensão chamada UNACCENT, que ignora completamente os acentos das palavras. Ou seja, com o UNACCENT, 'a' = 'ã'.
Para habilitar esse recurso, primeiramente você deve usar o PostgreSQL como BD. Após isso, deve adicionar a app 'django.contrib.postgres' na sua lista de aplicações instaladas. Algo assim:
INSTALLED_APPS = [
# apps do django
'django.contrib.postgres',
# apps de terceiros
# minhas apps
]
Após isso, você deve informar ao PostgreSQL que você quer essa extensão funcionando, pois ela não vem ativada por padrão no BD.
Entre via terminal no seu BD PostgreSQL:
psql meu_bd
ou algo como:
psql -h localhost -U usuario_do_bd -d meu_bd -W
O comando de entrada vai mudando conforme o SO e o usuário que você esteja utilizando.
Uma vez que você conseguiu entrar via psql, deverá ter algo parecido com isso:
psql (versao)
Type "help" for help.
meu_bd=#
Daí é só digitar o comando:
CREATE EXTENSION UNACCENT;
Agora no Django é só usar o lookup __unaccent nas buscas ❤️
Você também pode combinar os lookups no django, por esexmplo, o __unaccent com o __icontains. Ficaria mais ou menos assim:
Person.objects.filter(name__unaccent__icontains='arao')
Bônus
Existe também um lookup no PostgreSQL que retorna pesquisas similares. Por exemplo, seu usuário digitou "quato" ao invés de "quarto", com o lookup __trigam_similar podemos contornar esse pequeno erro. Você pode olhar melhor na documentação do Django.
Foto da capa by Markus Winkler on Unsplash