2010-04-06 20 views
18

Tengo una aplicación de blog realmente simple y quiero agregarle una característica de búsqueda realmente simple.Búsqueda simple en Django

Hay 3 campos clave para mi modelo.

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 

No necesito un Google. No quiero buscar comentarios (que se guardan en Disqus de todos modos). Solo quiero un conjunto de publicaciones filtradas por palabra clave clasificadas por fecha.

Todo lo que encuentro en Google para alguna forma de "django" y "búsqueda" viene con soluciones Haystack + backend horriblemente complicadas. Yo no necesito todo eso. No quiero consumir más recursos en una función de bajo uso (solía tener un cuadro de búsqueda antes de portarlo a Django y tenía quizás 4 búsquedas por mes).

La razón por la que me tomo el tiempo de preguntar aquí (en lugar de solo escribir un pequeño guión desordenado) es , esto ya existe en el administrador. Puede configurar las columnas para buscar y luego simplemente buscar y "simplemente funciona".

¿Hay alguna forma de obtener un control sobre la búsqueda proporcionada por el administrador y de insertarla en mi aplicación para usuarios?

Respuesta

35

Si desea realizar una búsqueda muy simple que puede utilizar las operaciones de búsqueda y icontainsQ 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)) 

También debe tener en cuenta que Haystack no tiene que ser "terriblemente complicada". Puede configurar el pajar con el backend de Whoosh en menos de 15 minutos.

Actualización 2016: En la versión 1.10 Django agregó a full text search support (solo PostgreSQL). Una respuesta a la pregunta original utilizando el nuevo módulo podría ser algo como esto:

from django.contrib.postgres.search import SearchVector 

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

El nuevo módulo de búsqueda de texto completo contiene muchas más características (por ejemplo, la clasificación por relevancia), puede read about them in the documentation.

+0

Estoy de acuerdo, Haystack + Whoosh es bastante fácil de poner en marcha. También podría ir con la búsqueda en el sitio de google si incluso eso es demasiado esfuerzo. –

+0

Por complicado, no solo me refería a la configuración. Es un código de millas más que este delineador. Sé que * tiene * mucho más con un rendimiento mucho mejor, pero la búsqueda rápida y sucia es todo lo que busco en este momento. ¡Gracias! @Stijn tirando de otro motor de búsqueda (yo iría con Bing porque tienen una API adecuada del lado del servidor) será mi próximo puerto de escala si no funciona la búsqueda sucia. – Oli

+0

Gracias por esto, muy útil. ¿Qué sucede si la búsqueda no arroja resultados? ¿Cómo generaríamos y agregaríamos un nuevo objeto BlogPost()? –

3

Utilizaría el operador __search. Está documentado en el Django QuerySet API Reference. También hay istartswith, que hace una búsqueda de inicios con insensible a mayúsculas y minúsculas.

Aquí está un ejemplo de trabajo (adaptado de mi propio sitio 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') 

Tenga en cuenta que __search sólo está disponible en MySQL y requiere la manipulación directa de la base de datos para agregar el índice de texto completo. Consulte el MySQL documentation para obtener detalles adicionales.

+0

El operador "__search" sólo funciona con ciertos backends y tipos de tablas que admiten índices de texto completo. – Cerin

+0

Gracias, he incluido esto en mi respuesta. – Frederik

5

Desde la fuente de 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 

claramente, utiliza las opciones de base de datos para realizar la búsqueda. Si nada más, debería poder reutilizar parte del código.

Así dice la documentación también: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

La búsqueda de texto completo, sin embargo, utiliza el índice de MySQL (sólo si está utilizando MySQL).

0

Si quieres que funcione igual que el administrador, puedes probar mi mini-lib Django simple search. Básicamente es un puerto de la funcionalidad de búsqueda de administrador. Instalarlo con pip:

pip install django-simple-search 

y usarlo como:

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)) 

También escribí un post al respecto: https://gregbrown.co/projects/django-simple-search

Cuestiones relacionadas