Cat

Django 29.2 Добавляем поиск на сайт, продолжение

В этом посте продолжим добавлять поиск на сайт, а именно: создадим форму для поиска, добавим её на все страницы сайта, сделаем собственного менеджера модели и встроим всё это в шаблоны.

Все статьи

Icon Link

Дополнительные материалы

Icon Link

Реклама

Icon Link
Сайт на Django proDream 16 Сентябрь 2023 Просмотров: 813

Форма поиска.

Напишем форму поиска. Для этого в директории приложения создадим новый файл 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 %}

 

На этом всё. Действий много, но они всё "точечные". Теперь на сайте есть работающий поиск.

Автор

    Нет комментариев

    Реклама