Для улучшения удобства использования разделов статей была внедрена сортировка статей по дате, заголовку, и количеству просмотров. Помимо этого была добавлена возможность поиска информации по статьям раздела. Реализуется эта возможность через несколько чекбоксов, которые добавляют названия колонок для сортировки в URL страницы, соответственно страница перезагружается.
Например, в модели данных есть несколько колонок
- title
- pub_date
- views
По ним и будем делать сортировку, которая в обычном варианте запроса выглядела бы так
Article.objects.all().order_by('title', 'pub_date', 'views')
Но поскольку мы используем чекбоксы, то варианты сортировку могу присутствовать, а могу и отсутствовать. Но не будем же мы писать if else блоки на каждую комбинацию чекбоксов? Конечно, нет.
Посмотрим для начала, как может быть написана форма для реализации сортировки. Сразу оговорюсь, что приведу вариант формы без стилизации, которая применена у меня на сайте. Дело в том, что для этого используется Bootstrap 4 Material Design, что несколько усложняем вариант вёрстки и добавит ряд лишних элементов в пример.
<form method="get"> <button type="submit" class="btn btn-sm btn-primary btn-raised mr-3">{% trans 'Сортировать' %}</button> <input name="sort" type="checkbox" value="title" {{ by_title }}>{% trans "по заголовку" %} <input name="sort" type="checkbox" value="pub_date" {{ by_date }}>{% trans "по дате" %} <input name="sort" type="checkbox" value="views" {{ by_views }}>{% trans "по просмотрам" %} </form>
Как видите, все чекбоксы в коде имеют имя sort, а значение value будет равно имени колонки, по которой можно будет включить сортировку.
Таким образом в URL будут фигурировать следующие аргументы
?sort=title&sort=pub_date&sort=views
Django позволяет извлечь все аргументы из запроса в качестве списка, который мы можем передать в метод order_by, чтобы выполнить сортировку.
И фактически представление для рендеринга раздела со статьями может выглядеть следующим образом
class SectionView(View): def get(self, request, slug): section = get_object_or_404(Section, slug=slug) sort = request.GET.getlist('sort') articles = section.article_set.all().order_by(*sort) return render( request=request, template_name='knowledge/section.html', context={ 'section': section, 'articles': articles } )
Обратите внимание, на то, что вместо метода get используется метод getlist , который возвращает список значений аргументов, если в запросе фигурировало одно и тоже имя аргумента несколько раз.
sort = request.GET.getlist('sort')
А далее с помощью указателя передаём список в качестве аргументов в метод order_by
articles = section.article_set.all().order_by(*sort)
Для Django рекомендую VDS-сервера хостера Timeweb .
Ну. Массово пока не использую фильтрации, поэтому не искал батареек. Так получилось, что даже не знал про django-filters.
хорошие статьи я много чего нашел тут интересного и нового... мне нравиться!
если вдруг интересно будет по фильтрам вот примерный код)
Спасибо за пример кода.
Когда буду внедрять больше поисковых виджетов на сайт, в первую очередь воспользуюсь вашим примером кода. Благо уже есть некоторые целевые места, где это можно применить.