2010-04-19 29 views
23

Tengo una lista de nombres que quiero que coincidan con mayúsculas y minúsculas, ¿hay alguna manera de hacerlo sin usar un ciclo como el siguiente?Django query case-insensitive list match

a = ['name1', 'name2', 'name3'] 
result = any([Name.objects.filter(name__iexact=name) for name in a]) 

Respuesta

27

Desafortunadamente, hay sin__iin campo de búsqueda. Pero hay un iregex que podría ser útil, así:

result = Name.objects.filter(name__iregex=r'(name1|name2|name3)') 

o incluso:

a = ['name1', 'name2', 'name3'] 
result = Name.objects.filter(name__iregex=r'(' + '|'.join(a) + ')') 

Tenga en cuenta que si una puede contener caracteres que son especiales en una expresión regular, es necesario escape de manera adecuada .

NOTICIAS: En Djano 1.7 es posible crear sus propias búsquedas, por lo que puede usar filter(name__iin=['name1', 'name2', 'name3']) luego de una inicialización adecuada. Vea https://docs.djangoproject.com/en/1.7/ref/models/lookups/ para más detalles.

+2

Postgres soporta índices de mayúsculas y minúsculas, así que por ese caso, puede ser más rápido para ejecutar consultas separadas "iexact" para cada elemento de un partido de iregex. En django, la búsqueda "iexact" de backend de back-end usa una transformación UPPER(), por lo que con un índice personalizado en UPPER() para esa fila es posible obtener una aceleración. – Evgeny

+5

Deseo que implementen __iin – JREAM

+0

@Evgeny Deseo que pudiera añadir una respuesta o darnos un enlace. ¡Gracias! –

3

Añadiendo a lo que dijo Rasmuj, escapan a cualquier usuario de entrada-al igual que

import re 
result = Name.objects.filter(name__iregex=r'(' + '|'.join([re.escape(n) for n in a]) + ')') 
3

Tenga en cuenta que al menos en MySQL tiene que establecer utf8_bin colación en sus tablas para hacer realidad las mayúsculas y minúsculas. De lo contrario, conservan las mayúsculas pero no distinguen entre mayúsculas y minúsculas. P.ej.

>>> models.Person.objects.filter(first__in=['John', 'Ringo']) 
[<Person: John Lennon>, <Person: Ringo Starr>] 
>>> models.Person.objects.filter(first__in=['joHn', 'RiNgO']) 
[<Person: John Lennon>, <Person: Ringo Starr>] 

Por lo tanto, si la portabilidad no es crucial y utiliza MySQL puede optar por ignorar el problema por completo.

15

en PostgreSQL usted podría intentar crear un índice de mayúsculas y minúsculas como se describe aquí:

https://stackoverflow.com/a/4124225/110274

continuación, ejecutar una consulta:

from django.db.models import Q 
name_filter = Q() 
for name in names: 
    name_filter |= Q(name__iexact=name) 
result = Name.objects.filter(name_filter) 

búsqueda Índice funcionará más rápido que la consulta de expresiones regulares a juego.

+0

Gracias! tengo la idea. –

+1

¡Cuidado con este código! Si los nombres de las variables están vacíos, el .filter devolverá todos los objetos de ese modelo. – Benjamin

1

Otra forma de utilizar este django query functions y anotación

from django.db.models.functions import Lower 
Record.objects.annotate(name_lower=Lower('name')).filter(name_lower__in=['two', 'one']