Evgenii Legotckoi
Evgenii Legotckoi28 февраля 2018 г. 4:57

Django - Урок 033. Передача списка аргументов в метод order_by для сортировки QuerySet

Для улучшения удобства использования разделов статей была внедрена сортировка статей по дате, заголовку, и количеству просмотров. Помимо этого была добавлена возможность поиска информации по статьям раздела. Реализуется эта возможность через несколько чекбоксов, которые добавляют названия колонок для сортировки в 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 .

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

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

bernar92
  • 16 мая 2018 г. 23:53
можно же это реализовать через django-filter!
Evgenii Legotckoi
  • 17 мая 2018 г. 2:05

Ну. Массово пока не использую фильтрации, поэтому не искал батареек. Так получилось, что даже не знал про django-filters.

Спасибо. Можете черкануть заметку, как аналог этой статье ;-)
bernar92
  • 17 мая 2018 г. 11:16

хорошие статьи я много чего нашел тут интересного и нового... мне нравиться!
если вдруг интересно будет по фильтрам вот примерный код)

import django_filters
from .models import Product

CHOICES =[
        ["name", "по алфавиту"],
        ["price", "дешевые сверху"],
        ["-price", "дорогие сверху"]
]


class ProductFilter(django_filters.FilterSet):
    name = django_filters.CharFilter(name='name', lookup_expr='icontains')
    category__slug = django_filters.CharFilter()
    price__gt = django_filters.NumberFilter(name='price', lookup_expr='gt')
    price__lt = django_filters.NumberFilter(name='price', lookup_expr='lt')
    ordering = django_filters.OrderingFilter(choices=CHOICES, required=True, empty_label=None,)

    class Meta:
        model = Product
        exclude = [field.name for field in Product._meta.fields]
        order_by_field = 'name'


from django_filters.views import FilterView
class EnumerationListView(FilterView):
    template_name = '.html'
    model = Lot
    paginate_by = 50
    filterset_class = ProductFilter
    context_object_name = 'product_list'

Evgenii Legotckoi
  • 17 мая 2018 г. 16:23

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
d
  • dsfs
  • 26 апреля 2024 г. 14:56

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80баллов,
  • Очки рейтинга4
d
  • dsfs
  • 26 апреля 2024 г. 14:45

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

  • Результат:50баллов,
  • Очки рейтинга-4
d
  • dsfs
  • 26 апреля 2024 г. 14:35

C++ - Тест 001. Первая программа и типы данных

  • Результат:73баллов,
  • Очки рейтинга1
Последние комментарии
k
kmssr9 февраля 2024 г. 5:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко5 февраля 2024 г. 12:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 21:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 19:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 декабря 2023 г. 8:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
BlinCT
BlinCT5 мая 2024 г. 15:46
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
BlinCT
BlinCT5 мая 2024 г. 15:44
добавить qlineseries в функции Давно я не работал с виджетами и с формами, на мой взгляд уже пережитов, и в управлении не очень удобное это все. Н оя у вас не увидел в коде где вы QCharts растягиваете на область парента.…
PS
Peter Son4 мая 2024 г. 3:57
Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
Evgenii Legotckoi
Evgenii Legotckoi3 мая 2024 г. 0:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderChe30 апреля 2024 г. 14:22
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

Следите за нами в социальных сетях