Django 29.2 Добавляем поиск на сайт, продолжение
В этом посте продолжим добавлять поиск на сайт, а именно: создадим форму для поиска, добавим её на все страницы сайта, сделаем собственного менеджера модели и встроим всё это в шаблоны.
Дополнительные материалы
Для скачивания материалов необходимо войти или зарегистрироваться
Файлы также можно получить в Telegram-боте по коду: 159845
Реклама
Форма поиска.
Напишем форму поиска. Для этого в директории приложения создадим новый файл forms.py
.
Внутри файла создадим класс SearchForm
унаследованный от forms.Form
.
Пропишем поле query
. Поле будет являться символьным полем с максимальной длинной в 100 символов.
Ниже напишем метод clean_query
. Данный метод будет очищать поисковый запрос от лишних пробелов внутри строки.
Код формы:
from django import forms
class SearchForm(forms.Form):
query = forms.CharField(max_length=100,
widget=forms.TextInput(
attrs={
'class': 'form-control me-2 mx-1',
'placeholder': 'Что ищем?',
}
))
def clean_query(self):
query = self.cleaned_data['query']
cleaned_query = " ".join(query.split())
return cleaned_query
Собственный менеджер для постов.
Нам также понадобится собственный менеджер, возвращающий только опубликованные посты.
Откроем файл models.py
и после импортов создадим класс PostManager
унаследованный от models.Manager
.
Внутри класса переопределим метод get_queryset
.
Код менеджера:
class PostManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status=PostModel.Status.PUBLISHED)
Далее найдём модель поста и добавим новое поле, определяющее нашего менеджера - post_manager = PostManager()
Контекстный процессор формы поиска.
Для того чтобы форма поиска была доступна на всех страницах, её удобнее всего передавать через контекстные процессоры.
Откроем или создадим файл, если у вас его нет, context_processors.py
.
В файле напишем функцию get_search_form
принимающую request
.
В теле функции сразу пишем возврат словаря, в котором будет ключ search_form
, а значением форма.
Код:
from blog import forms
def get_search_form(request):
return {'search_form': forms.SearchForm()}
Далее необходимо зарегистрировать функцию. Открываем файл settings.py
и находим переменную TEMPLATES
.
В ней находим список context_processors
и в него дописываем функцию - 'blog.context_processors.get_search_form',
Также не уходя из файла, в переменную INSTALLED_APPS
добавим строку - 'django.contrib.postgres',
.
URL-маршрут для страницы поиска.
Откроем файл urls.py
приложения и добавим новую строку:
path('search/', views.SearchPageView.as_view(), name='search_page'),
Указывая по какому адресу будет открываться поиск, какое представление за него отвечает и какое имя будет у маршрута.
Блок поиска в шапке сайта.
Для добавления поиска в шапку сайта, откройте файл header.html
и пропишите в удобном для вас месте следующий код:
<li class="nav-item">
<form class="d-flex" method="GET" action="{% url 'blog:search_page' %}">
{{ search_form.query }}
<button class="btn btn-primary search-btn" type="submit">Поиск</button>
</form>
</li>
Исправление пагинации для работы с поиском.
Поскольку у нас в запросе кроме номера страницы, ещё и переменная с поисковым запросом, стандартная пагинация работать не будет. Но исправление проблемы максимально простое.
Откроем файл pagination.html
и к каждой ссылке добавим проверку на наличие переменной query
. Если она есть, то в адрес добавляется переменная с запросом.
Например, так было:
<li class="page-item"><a class="page-link" href="?page={{ num_page }}">{{ num_page }}</a></li>
А так должно быть:
<li class="page-item"><a class="page-link" href="?page={{ num_page }}{% if request.GET.query %}&query={{ request.GET.query }}{% endif %}">{{ num_page }}</a></li>
Шаблон страницы поиска.
В шаблоне будем выводить поисковый запрос пользователя, результаты поиска и пагинацию.
Код шаблона:
{% extends "blog/base.html" %}
{% block title %}{{ query }}{% endblock %}
{% block content %}
<section class="info">
<div class="container">
<h1>Результаты по запросу: {{ query }}</h1>
<hr> </div> </section>
<section class="posts">
{% if results %}
<div class="container">
<div class="row">
<div class="col-lg-9 col-sm-12 cat-block">
{% for post in results %}
<div class="row">
<div class="col-lg-4 col-sm-12 d-flex align-items-center">
<img src="{{ post.image.url }}" alt="{{ post.title }}" class="img-fluid">
</div> <div class="col-lg-8 col-sm-12">
<h2 class="head2"><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h2>
<div class="mb-3">
<p class="lead"><a
href="{{ post.category.get_absolute_url }}">{{ post.category }}</a>
| {{ post.author }} | {{ post.publish | date:"d F Y" }} |
Просмотров: {{ post.views }}</p>
{% for tag in post.tags.all %}
<a href="{% url 'blog:tag_page' tag.slug %}"><span
class="badge bg-secondary">{{ tag.name }}</span></a>
{% endfor %}
</div>
{{ post.short_body | safe }}
</div>
</div> <hr class="m-3">
{% endfor %}
</div>
<div class="col-lg-3 col-sm-12">
<h2 class="mb-3">Ссылки</h2>
{% block social_links %}
{% include 'blog/index_page/social_links.html' %}
{% endblock %}
</div>
</div> <div class="col-12">
{% include "blog/modules/pagination.html" with page_obj=results %}
</div>
</div> {% else %}
<div class="container">
<h3>Нет результатов</h3>
</div> {% endif %}
</section>
{% endblock %}
На этом всё. Действий много, но они всё "точечные". Теперь на сайте есть работающий поиск.
Все статьи