Insights

Búsquedas sin acento en Django

Photo of the author: Igor Támara

Igor Támara

  •  

1 min read.

Buscar Bogotá o Bogota debería ofrecer el mismo resultado, los humanos no son tan estrictos, así que hay varias opciones para hacer que Django con Postgresql pueda encontrar cadenas sin importar si las personas escriben o no con acentos.  En esta entrada veremos cómo configurar postgresql y Django para lograr este efecto.  Personalmente creo que si hay que escribir con acentos, porque es distinto "bajo la escalera" a "bajó la escalera".


Nuestra aproximación empleará la extensión unaccent de postgresql, aunque postgresql desde la versión 9.1 ofrece collation para contar con índices en los idiomas que se requiera, Django no tiene incorporada la opción de collation para Postgresql.  Este artículo es válido hasta Django 1.6, de Django 1.7 en adelante ver al final.


Configurar postgresql


El primer paso es contar con la extensión
unaccent, para la base de datos destino se puede emplear

    psql -c "CREATE EXTENSION unaccent;" destino

La instalación de la extensión requiere que en un sistema Linux como Debian tenga el paquete contrib, por ejemplo, para postgresql 9.3:

    sudo apt-get install postgresql-contrib-9.3


Mokey Patch de Django


En un archivo que se invoque la mínima cantidad de veces se puede colocar el siguiente bloque de código

from django.db.backends.postgresql_psycopg2.base import DatabaseOperations
from django.db.backends.postgresql_psycopg2.base import DatabaseWrapper
def lookup_cast(self, lookup_type):
    if lookup_type in('icontains', 'istartswith', 'iexact'):
        return "UPPER(unaccent(%s::text))"
    elif lookup_type in('contains', 'startswith'):
        return "unaccent(%s::text)"
    else:
        return super(DatabaseOperations, self).lookup_cast(lookup_type)
def patch_unaccent():
    DatabaseOperations.lookup_cast = lookup_cast
    DatabaseWrapper.operators['icontains'] = 'LIKE UPPER(unaccent(%s))'
    DatabaseWrapper.operators['istartswith'] = 'LIKE UPPER(unaccent(%s))'
    DatabaseWrapper.operators['iexact'] = '= UPPER(unaccent(%s))'
    DatabaseWrapper.operators['contains'] = 'LIKE unaccent(%s)'
    DatabaseWrapper.operators['startswith'] = 'LIKE unaccent(%s)'
patch_unaccent()

Referentes

Learn more by receiving an email once a month.

Additional Insights

¿Cómo arreglar el error 403 de python-social-auth con Google?

Si tiene el siguiente error cuando trata de autenticarse con la cuenta de GoogleERROR 2014-05-29 21:25:06,289 base :: Intern...

Author Vera Mazhuga Vera Mazhuga

Editor favorito para áreas de texto

En esta entrada mostramos cómo emplear su editor de texto favorito para editar los contenidos de un TextArea en lugar de hace...

Photo of the author: Igor Támara Igor Támara

Cómo probar sitios web responsive

Nuestra empresa siempre busca y buscará la forma de que los proyectos en los que hemos trabajado se visualicen de maner...

Photo of the author: Carlos Niño Carlos Niño