Evgenii Legotckoi
4 октября 2016 г. 22:09

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

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

Но для того, чтобы выдача поисковых запросов походила больше на главную страницу, добавим возможность пагинации страниц выдачи, а результаты будут выводиться по 10 штук на одной странице. И для этого также будем использовать модуль django_bootstrap3.

В итоге имеем следующий план действий:

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

Добавляем приложение для поиска

Стандартный момент по созданию нового приложения в вашем проекте Django:

  1. python manage.db startapp search

На выходе получим новое приложение со следующей структурой:

  1. search/
  2. migrations/
  3. __init__.py
  4. __init__.py
  5. admin.py
  6. apps.py
  7. models.py
  8. tests.py
  9. views.py

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

  1. Для работы с postgres
  2. django_bootstrap3
  1. INSTALLED_APPS = [
  2. ...
  3. 'search.apps.SearchConfig',
  4. 'django.contrib.postgres',
  5. 'bootstrap3',
  6. ...
  7. ]

Добавляем urls поиска

Во-первых, необходимо добавить url шаблон, который отправит запрос в приложение search.

  1. from django.conf.urls import url, include
  2.  
  3. urlpatterns = [
  4. ...
  5. url(r'^search/', include('search.urls')),
  6. ]

Во-вторых, нужно добавить urls.py файл в само приложение search со следующим содержимым, чтобы настроить отправку запроса в представление.

  1. from django.conf.urls import url
  2.  
  3. from . import views
  4.  
  5. app_name = 'search'
  6. urlpatterns = [
  7. url(r'^$', views.ESearchView.as_view(), name='index'),
  8. ]

Форма поиска

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

Приведу тот вариант, который используется на данном сайте с использованием django-bootstrap3

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

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

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

Шаблон страницы поиска

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

Но самым главным отличием от главной страницы является то, что каким-то образом необходимо совместить перелистывание страниц при пагинации и сохранение запроса. Для этого можно подставлять кастомизированный URL в bootstrap_pagination. А именно url=last_question, который будет содержать последний запрос, который был задан в форме поиска. К этому URL автоматически будет добавлен номер страницы.

  1. {% extends 'home/base.html' %}
  2. {% load bootstrap3 %}
  3. {% block page %}
  4. <h1>Поиск</h1>
  5. {% if article_lists %}
  6. {% for article in article_lists %}
  7. <article>
  8. <a href="{{ article.get_absolute_url }}">
  9. <h2>{{ article.article_title }}</h2>
  10. </a>
  11. {{ article.desctription|safe }}
  12. <p><a class="btn btn-default btn-sm" href="{{ article.get_absolute_url }}">Читать далее</a></p>
  13. </article>
  14. {% endfor %}
  15. {% bootstrap_pagination article_lists url=last_question %}
  16. {% else %}
  17. <p>Не найдено публикаций по вашему запросу<br>Попробуйте повторить запрос с другой формулировкой</p>
  18. {% endif %}
  19. {% endblock %}

Представление поиска

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

  1. from django.shortcuts import render_to_response
  2. from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
  3. from django.views import View
  4.  
  5. from knowledge.models import Article
  6.  
  7.  
  8. class ESearchView(View):
  9. template_name = 'search/index.html'
  10.  
  11. def get(self, request, *args, **kwargs):
  12. context = {}
  13.  
  14. question = request.GET.get('q')
  15. if question is not None:
  16. search_articles = Article.objects.filter(article_content__search=question)
  17.  
  18. # формируем строку URL, которая будет содержать последний запрос
  19. # Это важно для корректной работы пагинации
  20. context['last_question'] = '?q=%s' % question
  21.  
  22. current_page = Paginator(search_articles, 10)
  23.  
  24. page = request.GET.get('page')
  25. try:
  26. context['article_lists'] = current_page.page(page)
  27. except PageNotAnInteger:
  28. context['article_lists'] = current_page.page(1)
  29. except EmptyPage:
  30. context['article_lists'] = current_page.page(current_page.num_pages)
  31.  
  32. return render_to_response(template_name=self.template_name, context=context)

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

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь