2010-04-06 3 views
18

У меня действительно простое приложение для блогов, и я хочу добавить к нему действительно простую функцию поиска.Простой поиск в Django

В моей модели есть 3 ключевых поля.

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 

Мне не нужен Google. Я не хочу искать комментарии (которые хранятся на Disqus в любом случае). Я просто хочу, чтобы дата-рейтинг, ключевое слово, отфильтрованное множество сообщений.

Все, что я нахожу в Google для какой-либо формы «джанго» и «поиска», возвращается с ужасно сложными решениями Haystack + backend. Я не необходимо все это. Я не хочу тратить больше ресурсов на функцию с низким уровнем использования (раньше у меня было окно поиска, прежде чем я поместил его в Django, и, возможно, это было 4 раза в месяц).

Причина, по которой я уделил время, чтобы спросить здесь (а не просто писать беспорядочный скрипт) это уже существует в администраторе. Вы можете установить столбцы для поиска, а затем просто выполнить поиск, и он «просто работает».

Есть ли способ получить ручку в указанном администратором поиске и потянуть его в мое приложение, ориентированное на пользователя?

ответ

35

Если вы хотите действительно простой поиск вы можете использовать поиск icontains и 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)) 

Вы должны также отметить, что Стог не должен быть «чудовищно сложным». Вы можете установить стог сена с помощью бэкэнда Whoosh менее чем за 15 минут.

Обновление 2016: В версии 1.10 Django добавлено a full text search support (только для PostgreSQL). Ответ на исходный вопрос, используя новый модуль может выглядеть примерно так:

from django.contrib.postgres.search import SearchVector 

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

Новый полный модуль поиска текст содержит гораздо больше функций (например, сортировка по релевантности), вы можете read about them in the documentation.

+0

Я согласен, Haystack + Whoosh довольно легко двигаться. Можете также пойти с поиском google, если даже это слишком много. –

+0

Сложный я имел в виду не только настройку. Это намного больше кода, чем этот однострочный. Я знаю, что это * делает намного больше с намного лучшей производительностью, но быстрый, грязный поиск - это все, что я нахожу в данный момент. Благодаря! @Stijn потянет другую поисковую систему (я бы поехал с Bing, потому что у них есть правильный серверный API) будет моим следующим портом захода, если грязный поиск не сработает. – Oli

+0

Спасибо за это, очень полезно. Что делать, если поиск не дает никаких результатов? Как мы сгенерируем и добавим новый объект BlogPost()? –

3

Вы должны использовать оператор __search. Он задокументирован в Django QuerySet API Reference. Также есть istartswith, который запускает без учета регистра с поиском.

Вот рабочий пример (взято из моего собственного сайта 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') 

Обратите внимание, что __search доступен только в MySQL и требует прямой манипуляции с базой данных, чтобы добавить полнотекстовый индекс. Дополнительную информацию см. На странице MySQL documentation.

+0

Оператор «__search» работает только с определенными движков и типов таблиц которые поддерживают полнотекстовые индексы. – Cerin

+0

Спасибо, я включил это в свой ответ. – Frederik

5

От источника Джанго: 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 

ясно, он использует параметры базы данных для выполнения поиска. Если ничего другого, вы должны иметь возможность повторно использовать часть кода.

Так говорит документация тоже: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

Полный поиск текста, однако, использует индекс MySQL (только если вы используете MySQL).

0

Если вы хотите, чтобы он работал точно так же, как администратор, вы можете попробовать мой мини-диск Django simple search. Это, в основном, порт функциональности поиска администратора. Установите его с пип:

pip install django-simple-search 

и использовать его как:

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

Я также написал в блоге об этом: https://gregbrown.co/projects/django-simple-search

Смежные вопросы