Простой поиск в Джанго - PullRequest
       3

Простой поиск в Джанго

25 голосов
/ 06 апреля 2010

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

В моей модели есть 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 поиска в месяц).

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

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

Ответы [ 4 ]

45 голосов
/ 06 апреля 2010

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

Также следует помнить, что 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)

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

5 голосов
/ 06 апреля 2010

Из источника 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

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

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

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

3 голосов
/ 06 апреля 2010

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

2 голосов
/ 21 апреля 2017

Если вы хотите, чтобы он работал так же, как администратор, вы можете попробовать мою мини-библиотеку Django simple search . Это в основном порт функции поиска администратора. Установите его с помощью 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))

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...