2011-10-06 12 views
15

Come posso eseguire una query sul nome completo in Django?Interrogazione del nome completo in Django

Per chiarire, io essenzialmente voglio fare creare una colonna temporanea, che unisce first_name e last_name per dare un nome completo, poi fare un COME su quello, in questo modo:

select [fields] from Users where CONCAT(first_name, ' ', last_name) LIKE '%John Smith%"; 

La query sopra sarebbe tornato a tutti gli utenti chiamato John Smith. Se possibile, vorrei evitare di utilizzare una chiamata SQL raw.

Il modello di cui sto parlando è il modello utente stock django.contrib.auth.models. Apportare modifiche al modello direttamente non è un problema.

Ad esempio, se un utente deve cercare "John Paul Smith", deve corrispondere agli utenti con un nome di "John Paul" e il cognome "Smith", così come gli utenti con nome "John" e il cognome "Paul Smith".

+0

Si prega di includere i vostri modelli Django. Se vuoi un "valore derivato" (come 'CONCAT (first_name, '', last_name)' in SQL) dovrai aggiungerlo al modello. Pertanto, includi il modello nella tua domanda. –

+0

Sei consapevole, BTW, che 'CONCAT (first_name, '', last_name) LIKE '% John Smith%" 'è terribilmente inefficiente? Usando' first_name LIKE'% John 'AND last_name LIKE' Smith% ''può essere più efficiente Perché usi il CONCAT quando ci sono modi non CONCAT per farlo? –

+0

È il modello utente standard django.contrib.auth.models. Stiamo già aggiungendo/modificando campi in questo modello, quindi le modifiche non sono un –

risposta

5

A meno che non mi manca qualcosa, è possibile utilizzare Python per interrogare il DB in questo modo:

from django.contrib.auth.models import User 
x = User.objects.filter(first_name='John', last_name='Smith') 

Edit: Per rispondere alla tua domanda:

Se avete bisogno di tornare 'John Paul Smith 'quando l'utente cerca' John Smith ', allora puoi usare' contains 'che si traduce in un LIKE SQL. Se hai solo bisogno della capacità di memorizzare il nome "John Paul", inserisci entrambi i nomi nella colonna first_name.

User.objects.filter(first_name__contains='John', last_name__contains='Smith') 

questo si traduce in:

SELECT * FROM USERS 
WHERE first_name LIKE'%John%' 
AND last_name LIKE'%Smith%' 
+1

Cosa succede se la query è "John Paul Smith"? –

+0

Se first_name == "John Paul" o last_name == "Paul Smith", corrisponderà comunque in questo modo. – jdi

+0

Quello che sto dicendo è, e se l'utente digitasse John Paul Smith? –

4
class User(models.Model): 
    first_name = models.CharField(max_length=64) 
    last_name = models.CharField(max_length=64) 
    full_name = models.CharField(max_length=128) 
    def save(self, *args, **kw): 
     self.full_name = '{0} {1}'.format(first_name, last_name) 
     super(User, self).save(*args, **kw) 
9

facile:

from django.db.models import Q 

def find_user_by_name(query_name): 
    qs = User.objects.all() 
    for term in query_name.split(): 
    qs = qs.filter(Q(first_name__icontains = term) | Q(last_name__icontains = term)) 
    return qs 

Dove QUERY_NAME potrebbe essere "John Smith" (ma sarebbe anche recuperare utente Smith John se presente).

+0

Ho iniziato a utilizzare questo e non appena c'è più di un termine di ricerca il tempo di risposta http va da 100ms a 5seconds. Qualche idea del perché questo sarebbe? – abarax

+0

Devi individuare dove si trova il problema. Banca dati? ORM? Modello? Esegui la query ('print qs.query') in un client sql per vedere se il problema è in db. In caso contrario, per esclusione (rimuovendo parti di codice), prova a indovinare se è presente nel modello. In caso contrario, potrebbe essere su ORM (provare le query restituendo meno righe). Stai affrontando un problema di ORM N + 1 (risolvilo con 'select_related' e' prefetch_related'). Riesci a indovinare qualcosa di sbagliato usando EXPLAIN (mysql/postgres) con la query (da un client sql)? Sei un tavolo massiccio? In tal caso, indicizzazione first_name e last_name facilitano il problema? – laffuste

+0

Grazie per i suggerimenti – abarax

0

Che dire di questo:

query = request.GET.get('query') 
users = [] 

try: 
    firstname = query.split(' ')[0] 
    lastname = query.split(' ')[1] 
    users += Users.objects.filter(firstname__icontains=firstname,lastname__icontains=lastname) 
    users += Users.objects.filter(firstname__icontains=lastname,lastname__icontains=firstname) 

users = set(users) 

collaudato!

Problemi correlati