2010-04-06 14 views
18

Ho un'applicazione per blog davvero semplice e voglio aggiungere una funzione di ricerca molto semplice.Ricerca semplice in Django

Ci sono 3 campi chiave per il mio modello.

class BlogPost(models.Model): 
    title = models.CharField(max_length=100) # the title 
    intro = models.TextField(blank=True, null=True) # an extract 
    content = models.TextField(blank=True, null=True) # full post 

Non ho bisogno di un Google. Non voglio cercare i commenti (che si trovano su Disqus comunque). Voglio solo un set di post con parole chiave, filtrato per parole chiave.

Tutto ciò che trovo su Google per una qualche forma di "django" e "ricerca" ritorna con le complicate soluzioni Haystack + backend. Io non ho bisogno di tutto questo. Non voglio consumare più risorse su una funzione a basso utilizzo (avevo una casella di ricerca prima di eseguire il porting su Django e aveva forse 4 ricerche al mese).

La ragione per cui sto prendendo tempo per chiedere qui (piuttosto che scrivere solo un piccolo script disordinato) è già esistente nell'admin. È possibile impostare le colonne su cui effettuare la ricerca, quindi cercare e "funziona".

C'è un modo per ottenere un controllo sulla ricerca fornita dall'amministratore e inserirla nell'app rivolta all'utente?

risposta

35

Se si vuole una ricerca molto semplice è possibile utilizzare icontains ricerca e Q object:

from django.db.models import Q 
results = BlogPost.objects.filter(Q(title__icontains=your_search_query) | Q(intro__icontains=your_search_query) | Q(content__icontains=your_search_query)) 

Si dovrebbe anche notare che Pagliaio non deve essere "orribilmente complicato". Puoi configurare il pagliaio con il backend Whoosh in meno di 15 minuti.

Aggiornamento 2016: Nella versione 1.10 Django ha aggiunto a full text search support (solo PostgreSQL). Una risposta alla domanda iniziale con il nuovo modulo potrebbe essere simile a questo:

from django.contrib.postgres.search import SearchVector 

results = BlogPost.objects.annotate(
    search=SearchVector('title', 'intro', 'content'), 
).filter(search=your_search_query) 

Il nuovo full modulo di ricerca di testo contiene molte più funzioni (ad esempio l'ordinamento per rilevanza), è possibile read about them in the documentation.

+0

Concordo, Haystack + Whoosh è abbastanza facile andare avanti. Potrebbe anche andare con la ricerca del sito di google se anche questo è troppo sforzo. –

+0

Complicitamente non intendevo solo l'installazione. È miglia più codice di questo one-liner. So che * fa * molto di più con prestazioni molto migliori ma la ricerca rapida e sporca è tutto ciò che sto cercando al momento. Grazie! @Stijn inserendo un altro motore di ricerca (io andrei con Bing perché hanno ancora un'API lato server corretta) sarà la mia prossima porta di chiamata se la ricerca sporca non funziona. – Oli

+0

Grazie per questo, molto utile. Cosa succede se la ricerca non fornisce risultati? Come dovremmo generare e aggiungere un nuovo oggetto BlogPost()? –

3

Si utilizzerà l'operatore __search. È documentato nello Django QuerySet API Reference. C'è anche istartswith, che inizia con maiuscole e minuscole, con la ricerca.

Ecco un esempio di lavoro (adattato dal mio sito Django):

def search(request): 
    try: 
     q = request.GET['q'] 
     posts = BlogPost.objects.filter(title__search=q) | \ 
       BlogPost.objects.filter(intro__search=q) | \ 
       BlogPost.objects.filter(content__search=q) 
     return render_to_response('search/results.html', {'posts':posts, 'q':q}) 
    except KeyError: 
     return render_to_response('search/results.html') 

Nota che __search è disponibile solo in MySQL e richiede la manipolazione diretta del database per aggiungere l'indice full-text. Vedi lo MySQL documentation per ulteriori dettagli.

+0

L'operatore "__search" funziona solo con alcuni backend e tipi di tabella che supporta gli indici di testo completo. – Cerin

+0

Grazie, ho incluso questo nella mia risposta. – Frederik

5

Dalla fonte django: http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/views/main.py

# Apply keyword searches. 
def construct_search(field_name): 
    if field_name.startswith('^'): 
     return "%s__istartswith" % field_name[1:] 
    elif field_name.startswith('='): 
     return "%s__iexact" % field_name[1:] 
    elif field_name.startswith('@'): 
     return "%s__search" % field_name[1:] 
    else: 
     return "%s__icontains" % field_name 

if self.search_fields and self.query: 
    for bit in self.query.split(): 
     or_queries = [models.Q(**{construct_search(str(field_name)): bit}) for field_name in self.search_fields] 
     qs = qs.filter(reduce(operator.or_, or_queries)) 
    for field_name in self.search_fields: 
     if '__' in field_name: 
      qs = qs.distinct() 
      break 

chiaramente, utilizza le opzioni di database per eseguire la ricerca. Se non altro, dovresti essere in grado di riutilizzare parte del codice da esso.

così dice la documentazione troppo: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

La ricerca a testo integrale, tuttavia, utilizza l'indice di mysql (solo se si utilizza mysql).

0

Se si desidera che funzioni come l'amministratore, è possibile provare il mio mini-lib Django simple search. È fondamentalmente una porta della funzionalità di ricerca dell'amministratore. Installarlo con pip:

pip install django-simple-search 

e utilizzarlo come:

from simple_search import search_filter 
from .models import BlogPost 

search_fields = ['^title', 'intro', 'content'] 
query = 'search term here' 
posts = BlogPost.objects.filter(search_filter(search_fields, query)) 

Ho anche scritto un post su di esso: https://gregbrown.co/projects/django-simple-search

Problemi correlati