Простой поиск в 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 для какой-то формы "django" и "search", возвращается с ужасно сложными решениями Haystack + backend. Мне это не нужно. Я не хочу тратить больше ресурсов на функцию с низким уровнем использования (раньше у меня было окно поиска до того, как я портировал Django, и, возможно, это было 4 раза в месяц).
Причина, по которой я собираюсь задать здесь (а не просто писать грязный маленький script), , уже существует в admin. Вы можете установить столбцы для поиска, а затем просто выполнить поиск, и он "просто работает".
Есть ли способ получить дескриптор в указанном администратором поиске и потянуть его в мое приложение, ориентированное на пользователя?
Ответы
Ответ 1
Если вы хотите действительно простой поиск, вы можете использовать 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))
Вы должны также отметить, что стог сена не должен быть "ужасно сложным". Вы можете настроить стог сена с помощью 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)
Новый модуль полнотекстового поиска содержит гораздо больше функций (например, сортировка по релевантности), о которых вы можете прочитать в документации.
Ответ 2
Из источника 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
Вы должны использовать оператор __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.
Ответ 4
Если вы хотите, чтобы он работал так же, как и администратор, вы можете попробовать мой мини-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))
Я также написал сообщение в блоге об этом: https://gregbrown.co/projects/django-simple-search