Django База [2023]: Реализация поиска с помощью PostgreSQL в Django 🔎 #34
Django

Django База [2023]: Реализация поиска с помощью PostgreSQL в Django 🔎 #34

Теги не заданы
Razilator

Django ORM уже имеются некоторые фильтры для поиска, но они не всегда соответствуют нашим требованиям. Вместо этого мы будем использовать поисковый движок полнотекстового поиска из модуля django.contrib.postgres в PostgreSQL, который обеспечивает широкие возможности для поиска на нашем сайте.

Статья по установке PostgreSQL в Django

Создание представления

Первое, что нам необходимо сделать, это создать нужное предсталвение для реализации поиска. В нашем файле views.py приложения blog добавим следующий код представления:

blog/views.py
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:

blog/urls.py
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, где наша поисковая форма, и меняем разметку на следующую:

templates/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>

Проверка работы поисковой системы

Ввел запрос: Django
Ввел запрос: Django
Ввел запрос: Тестовая
Ввел запрос: Тестовая

Отлично. Наш поиск работает так, как нам необходимо.

;