Для організації пошуку на сайті, що базується на Django , та використовує базу даних PostgreSQL можна використовувати модуль для пошуку по цій базі даних, що поставляється з Django. Тим більше, що цей пошук забезпечує повнотекстовий пошук достатньо для невеликого ресурсу.
Але для того, щоб видача пошукових запитів була схожа на головну сторінку, додамо можливість пагінації сторінок видачі, а результати будуть виводитися по 10 штук на одній сторінці. І для цього також використовуватимемо модуль django_bootstrap3.
У результаті маємо наступний план дій:
- Додаємо додаток для організації пошуку;
- Додаємо url пошуку;
- Додаємо форму пошуку;
- Описуємо шаблон сторінки пошуку.
- Описуємо уявлення для обробки видачі пошуку;
Додаємо програму для пошуку
Стандартний момент створення нової програми у вашому проекті Django:
python manage.db startapp search
На виході отримаємо новий додаток із наступною структурою:
search/ migrations/ __init__.py __init__.py admin.py apps.py models.py tests.py views.py
Підкоригуємо трохи файл settings.py . Додамо конфігурацію нашої програми, використовується та, що створиться за замовчуванням, також скористаємося двома модулями:
- Для роботи з postgres
- 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>
Розберемося у ключових моментах:
- У полі action вказана адреса куди надсилатиметься запит;
- Використовуватиметься метод GET, оскільки користувач може захотіти поділитися результатом пошуку;
- 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 .