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

Django - Урок 032. Расширенные параметры поиска

Django, Search

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

article = models.ForeignKey(Article, verbose_name=_("Статья"), null=True, blank=True)

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

Главным вопросом для меня было, как реализовать список тем на форуме так, чтобы не перегружать сайт дополнительными страницами, которые бы усложнили навигацию. Решение оказалось достаточно простым: добавить возможность поиска на форуме с дополнительными расширенными ключами поиска. А именно ключ article , который определял бы id статьи, по которому нужно отфильтровать все темы на форуме, которые содержат внешний ключ на статью с данным id .

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

Шаблон

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

<form class="input-group" method="get">
    <input name="q" type="text" class="form-control" placeholder="Поиск по форуму" value="{{ q }}">
    <span class="input-group-btn">
        <button type="submit" class="btn btn-default">Поиск</button>
    </span>
</form>

{% include 'forum/partials/index_topics_list.html' %}

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

Запрос может представлять собой обычное слово или словосочетание или пару ключ:значение . В данном случае пара будет выглядеть так article:95.

q - это соответственно текст поискового запроса.

В данном решении обрабатывается только одна пара ключа и значения. Этого достаточно для моих целей.

urls.py

В диспетчере путей нет ничего особенного.

# -*- coding: utf-8 -*-

from django.conf.urls import url

from . import views

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

views.py

Поиск по расширенному ключу делается через исключение, то есть если не удаётся выделить пару ключ/значение, то пытаемся использовать обычный поиск.

'''
Advanced search keys
'''
ARTICLE = 'article'

class IndexView(View):
    template_name = 'forum/index.html'

    def get(self, request):
        q = self.request.GET.get('q')
        if q:
            try:
                # Попытаемся разбить поисковый запрос на пару ключ/значение
                key, value = q.split(':')
                # Если удалось и нет исключения, то проверяем, является ли ключ исправным, а значение является ли числом
                if key == ARTICLE and value.isdigit():
                    # если да, то то фильтруем темы по внешнему ключу статей
                    object_list = Topic.objects.filter(article__pk=value).order_by('-lastmod')
                else:
                    # в противном случае выкидываем исключение
                    raise ValueError
            except ValueError:
                # При исключении делаем обычный поиск по заголовку тем, содержанию тем и содержанию сообщений в темах форума
                object_list = Topic.objects.filter(
                    Q(title__icontains=q) |
                    Q(content__icontains=q) |
                    Q(forumpost__content__icontains=q)
                ).distinct().order_by('-lastmod')
        else:
            # если поисковый запрос отсутствует, то выполняем обычную выборку статей
            object_list = Topic.objects.all().order_by('-lastmod')

        return render(
            request=request,
            template_name=self.template_name,
            context={
                'q': q or '',
                'object_list': get_paginated_page(request, object_list, 40),
                'last_question': request.get_full_path().replace(request.path, '') # url для пагинации с учётом вопроса
            }
        )

Про функцию get_paginated_page можете прочитать в статье про перезагрузку части контента страницы .

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

<a href="{% url 'forum:index' %}?q=article:{{ article.pk }}">

так и ключи расширенного поиска в стиле известных поисковых систем.

Для 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

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

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