© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

Django - Урок 012. Внедрение поиска по сайту с пагинацией результатов

Поиск, Postgres, Search

Для организации поиска на сайте, который основан на 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 .

Комментарии

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
15 июля 2018 г. 20:20
igorpodoba

C++ - Тест 003. Условия и циклы

  • Результат 92баллов,
  • Очки рейтинга8
15 июля 2018 г. 20:17
igorpodoba

C++ - Тест 002. Константы

  • Результат 91баллов,
  • Очки рейтинга8
14 июля 2018 г. 7:47
igorpodoba

C++ - Тест 003. Условия и циклы

  • Результат 71баллов,
  • Очки рейтинга1
Последние комментарии
14 июля 2018 г. 18:49
Евгений Легоцкой

Qt/C++ - Урок 049. QTranslator - динамический перевод мультиязычного приложения на Qt

У меня на руках есть один проект, где какие-то потуги с переводами и подключением этого добра в CMAKE делались.Но там файл перевода добавляется прямо в ресурсы проекта. То есть бинарных qm файл...
14 июля 2018 г. 18:35
Евгений Легоцкой

Django - Урок 036. Как добавить аутентификацию через социальные сети. ВКонтакте

Не, не будет, в данной батарейке уже есть необходимый функционал по разрулированию этой проблемы. Аутентификации из разных социальных сетей будут сливаться на один аккаунт. Так что всё нормаль...
14 июля 2018 г. 4:17
Gerych

Django - Урок 036. Как добавить аутентификацию через социальные сети. ВКонтакте

Мне интересно что будет если в обеих сетях в авторизации одинаковый еmail. Не выведет ли ошибку ?
13 июля 2018 г. 11:55
Arrow

Qt/C++ - Урок 049. QTranslator - динамический перевод мультиязычного приложения на Qt

Хорошая статья. Только один вопрос как это сделать для CMake? Интересует именно запись в CMakeList TRANSLATIONS += QtLanguage_ru.ts CODECFORSRC = UTF-8 П...
Сейчас обсуждают на форуме
14 июля 2018 г. 18:56
Евгений Легоцкой

Как сделать пустое поле в QDateEdit

Слишком много возни, чтобы подробно объяснить, что нужно сделать.... тем более, что у вас ещё зависимость на базу данных... Для начала нужно наследоваться от QCalendarWidget, посколь...
12 июля 2018 г. 15:02
незнаток

Перенос значений таблицы в другую таблицу

void Opisanie::perevod(){ QString mil; int mf = ui->table1->rowCount(); for(int ik = 0; ik < mf; ik++) { QString tu = ui->table1->model()->data(ui...
12 июля 2018 г. 7:46
Евгений Легоцкой

OpenSSL на Windows10

Совсем забыл. Вот в этом посте есть ссылка на скачивание openssl библиотек для msvc-2015
11 июля 2018 г. 16:05
Ruslan Polupan

Наследование от QLineEdit

Из опыта разработки в нашей конторе (для программирование хобби я техподдержка): Если есть возможность переложить логику приложения на базу данных то это лутший вариант. Т.е. использовать по м...

Рекомендуемые страницы