Django База [2023]: Реализация поиска с помощью PostgreSQL в Django 🔎 #34
Django ORM уже имеются некоторые фильтры для поиска, но они не всегда соответствуют нашим требованиям. Вместо этого мы будем использовать поисковый движок полнотекстового поиска из модуля django.contrib.postgres в PostgreSQL, который обеспечивает широкие возможности для поиска на нашем сайте.
Если вы хотите выразить благодарность автору сайта, статей и курса по Django, вы можете сделать это по ссылке ниже:
Статья по установке PostgreSQL в Django
Создание представления
Первое, что нам необходимо сделать, это создать нужное предсталвение для реализации поиска. В нашем файле views.py приложения blog добавим следующий код представления:
from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank
from django.views.generic import ListView
class ArticleSearchResultView(ListView):
"""
Реализация поиска статей на сайте
"""
model = Article
context_object_name = 'articles'
paginate_by = 10
allow_empty = True
template_name = 'blog/articles_list.html'
def get_queryset(self):
query = self.request.GET.get('do')
search_vector = SearchVector('full_description', weight='B') + SearchVector('title', weight='A')
search_query = SearchQuery(query)
return (self.model.objects.annotate(rank=SearchRank(search_vector, search_query)).filter(rank__gte=0.3).order_by('-rank'))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = f'Результаты поиска: {self.request.GET.get("do")}'
return context
Данный код представляет собой реализацию поиска статей на сайте. Он использует класс ListView из Django для отображения списка статей, соответствующих запросу пользователя.
В методе get_queryset()
происходит поиск статей с помощью полнотекстового поискового движка из модуля django.contrib.postgres.search в PostgreSQL. Для этого формируется поисковый вектор (search_vector), содержащий поля, по которым будет производиться поиск, и задаются веса (weight) каждого поля. Затем формируется поисковый запрос (search_query) на основе запроса пользователя (query), который был передан через GET-параметр do. Поиск выполняется с помощью методов SearchRank и filter модели Article. Результаты сортируются по релевантности в обратном порядке.
Метод get_context_data()
формирует контекст для отображения найденных статей в шаблоне.
Обработка представления в urls.py
Следующим действием нам нужно обработать созданное представление в urls.py файле нашего приложения blog:
from django.urls import path
from .views import ArticleListView, ArticleDetailView, ArticleByCategoryListView, articles_list, ArticleCreateView, \
ArticleUpdateView, ArticleDeleteView, CommentCreateView, ArticleByTagListView, ArticleSearchResultView
urlpatterns = [
path('', ArticleListView.as_view(), name='home'),
path('articles/', articles_list, name='articles_by_page'),
path('articles/create/', ArticleCreateView.as_view(), name='articles_create'),
path('articles/<str:slug>/update/', ArticleUpdateView.as_view(), name='articles_update'),
path('articles/<str:slug>/delete/', ArticleDeleteView.as_view(), name='articles_delete'),
path('articles/<str:slug>/', ArticleDetailView.as_view(), name='articles_detail'),
path('articles/<int:pk>/comments/create/', CommentCreateView.as_view(), name='comment_create_view'),
path('articles/tags/<str:tag>/', ArticleByTagListView.as_view(), name='articles_by_tags'),
path('category/<str:slug>/', ArticleByCategoryListView.as_view(), name="articles_by_category"),
path('search/', ArticleSearchResultView.as_view(), name='search'),
]
Обязательно добавляем юрл в самый конец, для правильной обработки.
Изменение шаблона формы поиска
Переходим в header.html, где наша поисковая форма, и меняем разметку на следующую:
<form class="col-12 col-lg-auto mb-2 mb-lg-0 me-lg-auto" role="search" method="get" action="{% url 'search' %}">
<input type="search" class="form-control" placeholder="Search..." aria-label="Search" name='do' autocomplete="off" id="search">
</form>
Проверка работы поисковой системы
Отлично. Наш поиск работает так, как нам необходимо.