Простой поиск в Django

21

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

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

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

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

    
задан Oli 06.04.2010 в 13:43
источник

4 ответа

40

Если вы хотите действительно простой поиск, вы можете использовать icontains поиск и % объекта co_de% :

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

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

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

from django.contrib.postgres.search import SearchVector

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

Новый модуль полнотекстового поиска содержит намного больше функций (например, сортировка по релевантности), вы можете читайте о них в документации .

    
ответ дан Ludwik Trammer 06.04.2010 в 13:55
  • Я согласен, Haystack + Whoosh довольно легко двигаться. Можете также пойти с поиском google, если даже это слишком много. –  Stijn Debrouwere 06.04.2010 в 15:23
  • Сложным я не просто означал настройку. Это намного больше кода, чем этот однострочный. Я знаю, что это намного больше, с гораздо более высокой производительностью, но быстрый, грязный поиск - это все, что я нахожу сейчас. Спасибо! @Stijn потянет другую поисковую систему (я бы поехал с Bing, потому что у них есть правильный серверный API) будет моим следующим портом захода, если грязный поиск не сработает. –  Oli 07.04.2010 в 16:03
  • Спасибо за это, очень полезно. Что делать, если поиск не дает никаких результатов? Как мы сгенерируем и добавим новый объект BlogPost ()? –  xandermonkey 06.04.2017 в 19:31
5

Из источника django: Ссылка

# 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

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

Так говорит и документация: Ссылка

В полнотекстовом поиске используется индекс mysql (только если вы используете mysql).

    
ответ дан Lakshman Prasad 06.04.2010 в 14:03
3

Вы должны использовать оператор __search. Он описан в Справочнике API Django QuerySet . Существует также 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 .

    
ответ дан Frederik 06.04.2010 в 13:55
  • Оператор «__search» работает только с определенными типами бэкэнд и таблиц, которые поддерживают полнотекстовые индексы. –  Cerin 20.08.2013 в 16:58
  • Спасибо, я включил это в свой ответ. –  Frederik 20.08.2013 в 20:42
0

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

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

Я также написал сообщение в блоге об этом: Ссылка

    
ответ дан Greg 20.04.2017 в 23:37