Evgenii Legotckoi
Evgenii Legotckoi04 жовтня 2016 р. 12:09

Django - Підручник 012. Пошук по сайту з розбиттям сторінок на основі Django

Для організації пошуку на сайті, що базується на Django , та використовує базу даних PostgreSQL можна використовувати модуль для пошуку по цій базі даних, що поставляється з Django. Тим більше, що цей пошук забезпечує повнотекстовий пошук достатньо для невеликого ресурсу.

Але для того, щоб видача пошукових запитів була схожа на головну сторінку, додамо можливість пагінації сторінок видачі, а результати будуть виводитися по 10 штук на одній сторінці. І для цього також використовуватимемо модуль django_bootstrap3.

У результаті маємо наступний план дій:

  1. Додаємо додаток для організації пошуку;
  2. Додаємо url пошуку;
  3. Додаємо форму пошуку;
  4. Описуємо шаблон сторінки пошуку.
  5. Описуємо уявлення для обробки видачі пошуку;

Додаємо програму для пошуку

Стандартний момент створення нової програми у вашому проекті Django:

python manage.db startapp search

На виході отримаємо новий додаток із наступною структурою:

search/
    migrations/
        __init__.py
    __init__.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py

Підкоригуємо трохи файл settings.py . Додамо конфігурацію нашої програми, використовується та, що створиться за замовчуванням, також скористаємося двома модулями:

  1. Для роботи з postgres
  2. django_bootstrap3
INSTALLED_APPS = [
    ...
    'search.apps.SearchConfig',
    'django.contrib.postgres',
    'bootstrap3',
    ...
]

Додаємо urls пошуку

По-перше, необхідно додати url шаблон, який надішле запит до програми search.

from django.conf.urls import url, include

urlpatterns = [
    ...
    url(r'^search/', include('search.urls')),
]

По-друге, потрібно додати urls.py файл в саму програму search з наступним вмістом, щоб налаштувати відправку запиту в представлення.

from django.conf.urls import url

from . import views

app_name = 'search'
urlpatterns = [
    url(r'^$', views.ESearchView.as_view(), name='index'),
]

Форма пошуку

Форма пошуку додана до базового шаблону base.html у додатку home , який успадковуватиметься шаблоном сторінки пошуку.

Наведу той варіант, який використовується на даному сайті за допомогою django-bootstrap3

{% load bootstrap3 %}
<form action="{% url 'search:index' %}" class="navbar-form navbar-left" method="get">
    <div class="input-group">
        <input id="search" name="q" type="text" class="form-control" placeholder="Поиск">
        <span class="input-group-btn">
            <button type="submit" class="btn btn-default">{% bootstrap_icon 'search' %}</button>
        </span>
    </div>
</form>

Розберемося у ключових моментах:

  1. У полі action вказана адреса куди надсилатиметься запит;
  2. Використовуватиметься метод GET, оскільки користувач може захотіти поділитися результатом пошуку;
  3. bootstrap_icon підвантажує іконки з набору glyphicons.

Шаблон сторінки пошуку

Для видачі результатів я використав організацію зовнішнього вигляду таку саму, як і на головній сторінці сайту. Докладніше про це можете почитати у статті про впровадження пагінації .

Але найголовнішою відмінністю від головної сторінки є те, що якимось чином необхідно поєднати перегортання сторінок під час пагінації та збереження запиту. Для цього можна підставляти кастомізований URL в bootstrap_pagination. А саме url=last_question, який міститиме останній запит, який був заданий у формі пошуку. До цієї URL-адреси автоматично буде додано номер сторінки.

{% extends 'home/base.html' %}
{% load bootstrap3 %}
{% block page %}
    <h1>Поиск</h1>
    {% if article_lists %}
        {% for article in article_lists %}
            <article>
                <a href="{{ article.get_absolute_url }}">
                    <h2>{{ article.article_title }}</h2>
                </a>
                {{ article.desctription|safe }}
                <p><a class="btn btn-default btn-sm" href="{{ article.get_absolute_url }}">Читать далее</a></p>
            </article>
        {% endfor %}
        {% bootstrap_pagination article_lists url=last_question %}
    {% else %}
        <p>Не найдено публикаций по вашему запросу<br>Попробуйте повторить запрос с другой формулировкой</p>
    {% endif %}
{% endblock %}

Подання пошуку

Важливим моментом є тут те, що із запиту необхідно підготувати URL, який міститиме останній запит і підставлятиметься в кнопочки пагінації. Інакше при натисканні кнопки пагінації пошук буде помилковим і швидше за все отримуватимете помилка 500 .

from django.shortcuts import render_to_response
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.views import View

from knowledge.models import Article


class ESearchView(View):
    template_name = 'search/index.html'

    def get(self, request, *args, **kwargs):
        context = {}

        question = request.GET.get('q')
        if question is not None:
            search_articles = Article.objects.filter(article_content__search=question)

            # формируем строку URL, которая будет содержать последний запрос
            # Это важно для корректной работы пагинации
            context['last_question'] = '?q=%s' % question

            current_page = Paginator(search_articles, 10)

            page = request.GET.get('page')
            try:
                context['article_lists'] = current_page.page(page)
            except PageNotAnInteger:
                context['article_lists'] = current_page.page(1)
            except EmptyPage:
                context['article_lists'] = current_page.page(current_page.num_pages)

        return render_to_response(template_name=self.template_name, context=context)

Для Django рекомендую VDS-сервера хостера Timeweb .

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
Ua

Qt - Тест 001. Сигналы и слоты

  • Результат:84бали,
  • Рейтинг балів4
Ua

Qt - Тест 001. Сигналы и слоты

  • Результат:42бали,
  • Рейтинг балів-8
ОК

Qt - Тест 001. Сигналы и слоты

  • Результат:47бали,
  • Рейтинг балів-6
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Дмитрий
Дмитрий03 лютого 2025 р. 06:24
Создание deb-пакета. Как создать ярлык на рабочем столе после установки собственного deb-пакета? Всем привет. Сделал свой deb-пакет с программой. Всё устанавливается и работает. Ставлю по пути /usr/bin/my_application. Как для пользователя при установке пакета сразу создать ярлык на раб…
NW
Nayo Wai30 січня 2025 р. 09:22
не запускается компьютер!!! Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
n
nkly03 січня 2025 р. 02:52
Нужно запретить перемещение только некоторых итемов, остальные перемещать можно. Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
M
Marsel16 серпня 2023 р. 14:26
OAuth2.0 через VK, получение email Спасибо большое за помощь и простите за то что отнял время своей невнимательностью.
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.

Слідкуйте за нами в соціальних мережах