Busqueda de nombre completo en Django

262 views
Skip to first unread message

Jorge Andrés Vergara Ebratt

unread,
May 4, 2015, 7:05:37 PM5/4/15
to djan...@googlegroups.com
Hola a todos,

Estoy intentando crear una búsqueda de nombre completo en mi aplicación, los coloco en contexto:

Tengo un campo nombre donde va el nombre completo de la persona y estoy usando una query para la búsqueda, que pasa:

lista_clientes = list(Cliente.objects.filter(persona__nombre__icontains = busqueda))

Al momento de yo hacer eso me 'funciona' más o menos:

Si el nombre es Jorge Andres Vergara por ejemplo, me pasa lo siguiente:
Si busco por cualquiera de los términos individuales me encuentro, si busco por el nombre completo también, o si coloco cualquier secuencia de letras que se encuentren dentro del nombre en ese orden, ejemplo:

Si yo busco Andres Ver, me encuentra sin problemas, mi problema radica en que no me puedo volar el segundo nombre, si yo busco por Jorge Vergara, me sale que no encuentra resultados, por que Django en icontains utiliza un LIKE %termino%.

Alguien sabe como puedo lograr lo que busco? El admin de Django lo hace sin problemas, cuando usas un search_fields el admin te lo encuentra sin ningún problema.



Agradezco de antemano la atención y ayuda

Jorge Andrés Vergara Ebratt

unread,
May 6, 2015, 6:22:33 AM5/6/15
to djan...@googlegroups.com
Hola a todos,

Por si hay alguien teniendo el mismo problema hoy logré solucionarlo:

Fue simplemente hacer un split de la búsqueda y luego comparar con todos:

for term in busqueda.split():
    lista_clientes = list(Cliente.objects.filter(Q(usuario = request.user),
        Q(persona__nombre__icontains = term)))

Con eso ya si el nombre es JORGE ANDRES VERGARA EBRATT me arroja resultado buscando por cualquiera de los 4 terminos o los 4 si es caso sin importar el orden en que los coloque


Saludos!

Esau Rodriguez

unread,
May 6, 2015, 6:53:52 AM5/6/15
to djan...@googlegroups.com
Podrías usar una reducción con el operador or (Es lo mismo que hace la
interfaz administrativa)

Algo así

{code}
from operator import __or__ as OR
lst = busqueda.split()
qs = Cliente.objects.filter(Q(usuario = request.user), reduce(OR, lst))
{code}

Con eso solo tendrias una query a base de datos y no el numero de
terminos que introduzcas.

De todos modos si quieres hacer algo mas serio deberias mirarte
django-haystack [1]. Que te permite hacer busquedas por similitudes.

[1] http://haystacksearch.org/
> --
> --
> Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios del
> Framework Django de habla hispana" de Grupos de Google.
> Si quieres publicar en este grupo, envía un mensaje de correo
> electrónico a djan...@googlegroups.com
> Para anular la suscripción a este grupo, envíe un mensaje a
> django-es-...@googlegroups.com
> Para obtener más opciones, visita este grupo en
> http://groups.google.com.bo/group/django-es.
> ---
> Has recibido este mensaje porque estás suscrito al grupo "Django-es" de
> Grupos de Google.
> Para anular la suscripción a este grupo y dejar de recibir sus mensajes,
> envía un correo electrónico a django-es+...@googlegroups.com.
> Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Esaú Rodríguez
esa...@gmail.com

Jorge Andrés Vergara Ebratt

unread,
May 6, 2015, 7:22:26 AM5/6/15
to djan...@googlegroups.com
Hola Esaú,

Muchas gracias, probaré tu solución...

Con respecto a Haystack si lo he mirado, pero como solo necesito es filtrar una lista de personas era como matar un mosquito con una escopeta :)

Para obtener más opciones, visita https://groups.google.com/d/optout.

Jorge Andrés Vergara Ebratt

unread,
May 7, 2015, 10:11:08 AM5/7/15
to djan...@googlegroups.com
Yo por acá de nuevo jeje, es que el OR no me sirvió, por que necesito un AND, o sea, que esté nombre y apellido dentro del nombre completo, entonces neceando bastante logré solucionarlo sin hacer querysets dentro de un for, les comparto mi solución por si alguien se encuentra con algo similar:

if request.GET.get('busqueda'):
        busqueda = request.GET['busqueda']

        values = []
        for term in busqueda.split():
            values.append(term)

        # Aquí creamos el listado de querys
        queries = [Q(persona__nombre__icontains =value) for value in values]

        #Sacamos una query del listado
        query = queries.pop()
        
        #Hacemos AND de esa query con todas las demás
        for item in queries:
            query &= item

        lista_clientes = Cliente.objects.filter(usuario = request.user, query)

Esau Rodriguez

unread,
May 8, 2015, 9:21:16 AM5/8/15
to django-es@googlegroups com

También hay un reduce.and  creo

Reply all
Reply to author
Forward
0 new messages