Django rest framework фильтрация

Обновлено: 05.07.2024

Началось всё с того, что мне предложили в рамках предмета "Основы веб-программирования" поучаствовать в проекте, вместо проделывания лабораторных работ и курсовой, поскольку я заявил о том, что хотел быть делать нечто отдалённое от общего курса (и так уже достаточно знаний было по связке DRF + Vue, хотелось чего-то нового). И вот в одном из своих PR на github я решил использовать полнотекстовый поиск (задание намекало на это) для фильтрации контента, что заставило меня обратиться к документации Django в поисках того, каким же образом лучше это дело реализовать. Думаю, вы знаете большую часть из тех методов, что были там предложены (contains, icontains, trigram_similar). Все они подходят для каких-то конкретных задач, но не слишком хороши в, именно, полнотекстовом поиске. Пролистав чуть ниже, я наткнулся на раздел, в котором говорилось о взаимодействии Django и Pgsql для реализации document-based поиска, что меня привлекло, поскольку в постгре встроен инструмент для реализации этого самого [полнотекстового] поиска. И я решил, что скорее всего, django просто предоставляет API к этому поиску, исходя из чего такое решение должно работать и точнее и быстрее, чем любые другие варианты. Преподаватель мне не слишком поверил, мы с ним поспорили, и он предложил провести исследование на эту тему. И вот я здесь.

Начало работы

Первая проблема, которая передо мной встала — поиск мокапа БД, чтобы не придумать каких-нибудь непонятных штук самому и я отправился гуглить и читать вики постгреса. В итоге остановился на их демо базе о полётах по России.

Хорошо, база найдена. Теперь нужно определиться в том, какие способы фильтрации будут использоваться для сравнения. Первое, что я бы хотел использовать, разумеется, стандартный метод search из django.contrib.postgres.search. Второе — contains (ищет слово в строке) и icontains (предоставляет данные, игнорируя акценты, например: по запросу "Helen" будет результат: <Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>), которые предоставляет сам django. Все эти способы фильтрации я так же хочу сравнить со встроенным поиском внутри postgresql. Искать я решил по таблице tickets в версии small она содержит 366733 записей. Поиск будет происходить по полю passenger_name, где, как нетрудно догадаться, содержится имя пассажира. Написано оно транслитом.

Дать django возможность работать с уже существующей БД

Вторая проблема — разрешить django только чтение данных из нашей демонстрационной БД. Покопавшись ещё в документации django я нашёл каким же образом, можно составить модельки по существующей БД, чтобы не перепечатывать ручками всё:

Выбор метрик

Изначально я подумал, что считать время фильтрации в питоне получится, используя таймер для получения времени исполнения скрипта, и дополнительной метрикой должно было стать время исполнения запроса через curl, поскольку это показывает приблизительное время, за которое отфильтрованные данные дойдут до конечного пользователя. Кроме этого, следует сравнивать это время с эталонным (прямым исполнением соответствующих запросов в БД).

Фильтруем в django

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

A QuerySet is iterable, and it executes its database query the first time you iterate over it. For example, this will print the headline of all entries in the database:

Contains

Начнём с contains, по сути, он работает как WHERE LIKE.

Для того, чтобы получить результат из curl я выполнял запрос следующим образом (считается в секундах):

Свёл всё в таблице, на соответствующем листе.

Но если резюмировать — отклонение от скорости фильтрации внутри самого постгреса достаточно большое, и по факту исполнение такого запроса к серверу займёт от 140 до 1400 мс. Не претендую на истину, но работает всё приблизительно так. А время самой фильтрации через ORM займёт от 73 до 600 мс, в то время как такая же фильтрация внутри постгреса выполняется за промежуток от 55 до 100 мс.

Icontains

Icontains работает несколько по-другому (он приводит всё к одному виду, чтобы сравнение было более близким). Код для вьюшки использовался почти аналогичный, только вместо contains — icontains. Вот и вся разница.

По итогу, отклонение в данном случае уже меньше, поскольку и сам постгрес начал тратить намного большее времени на исполнение запроса (порядка 300 мс), а исполнение такого запроса к серверу займёт у клиента от 200 до 1500 мс. Фильтрация через ORM — от до 200 до 700 мс.

Full text search (через django.contrib.postgres)

Поскольку индексов никаких создано не было, full text search довольно сильно и вполне ощутимо проигрывает прошлым вариантам. Время исполнения запроса в постгресе колеблется около 1300 мс, а запрос к серверу занимает от 1000 до 1700 мс. При этом, фильтрация через ORM — укладывается в промежуток от 1000 до 1450 мс.

Full text search (через rest_framework.filters, точнее — SearchFilter)

Если не использвоать именно FTS, то результаты получаются сравнимыми с FTS внутри постгре, но хуже, чем contains и icontains. От 200 до 1710 мс.

А с использованием FTS эффективность повышается, отклонение сводится к минимальному. В среднем, это займёт от 800 до 1120 мс.

Использование фильтров через модуль django-filter

Результаты почти совпали со стандартными contains и icontains, поэтому смысла детально это рассматривать не вижу. Да и в целом, модуль django-filter не показал какого-то ощутимого преимущества перед стандартными средствами фильтрации Django ORM.

Так что в итоге?

Если у вас есть большой объём данных — нужно прописывать нормальные индексы и использовать полнотекстовый поиск (разумеется, только в том случае, когда соответствует вашим целям) с радостью и счастьем, потому что он решает довольно широкий круг проблем. Но вот всегда ли в нём есть необходимость — уже решать вам. Я усвоил для себя, что в некоторых случаях (когда не стоит задачи именно полнотекстового поиска, а есть поиск по подстроке, который реализуется с помощью contains/icontains) лучше вовсе не использовать полнотекстовый поиск, потому что индексы в определённый момент начинают кушать всё больше и больше памяти вашего сервера, что, скорее всего, негативно скажется на работе вашего сервера.

В целом, моё понимание некоторых внутренних механизмов работы django благодаря этому исследованию устаканилось. И пришло, наконец, осознание разницы между поиском по подстроке и полнотекстовым поиском. Разнице в их реализации через Django ORM.

Корневой QuerySet, предоставляемый менеджером, описывает все объекты в таблице базы данных. Обычно, однако, вам нужно выбрать только подмножество полного набора объектов.

‒ Django documentation

По умолчанию общие представления списков в REST framework возвращают весь набор запросов для менеджера модели. Часто вы хотите, чтобы ваш API ограничивал элементы, возвращаемые набором запросов.

Самый простой способ фильтровать набор запросов любого представления, которое является подклассом GenericAPIView , - это переопределить метод .get_queryset() .

Переопределение этого метода позволяет вам настроить набор запросов, возвращаемый представлением, различными способами.

Фильтрация по текущему пользователю¶

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

Фильтрация по URL-адресу¶

Другой стиль фильтрации может включать ограничение набора запросов на основе некоторой части URL.

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

Затем вы можете написать представление, которое возвращает набор запросов на покупку, отфильтрованный по имени пользователя в части URL:

Фильтрация по параметрам запроса¶

Последним примером фильтрации начального набора запросов может быть определение начального набора запросов на основе параметров запроса в url.

Помимо возможности переопределения набора запросов по умолчанию, REST framework также включает поддержку общих бэкендов фильтрации, которые позволяют легко создавать сложные поиски и фильтры.

Общие фильтры также могут быть представлены в виде элементов управления HTML в просматриваемом API и API администратора.

Filter Example

Настройка бэкендов фильтров¶

Бэкенды фильтров по умолчанию могут быть установлены глобально, с помощью параметра DEFAULT_FILTER_BACKENDS . Например.

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

Фильтрация и поиск объектов¶

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

Например, учитывая предыдущий пример и продукт с идентификатором 4675 , следующий URL либо вернет соответствующий объект, либо выдаст ответ 404, в зависимости от того, были ли выполнены условия фильтрации для данного экземпляра продукта:

Переопределение начального набора queryset¶

Обратите внимание, что вы можете использовать и переопределенный .get_queryset() , и общую фильтрацию вместе, и все будет работать, как ожидалось. Например, если Product имеет отношения «многие-ко-многим» с User , названными purchase , вы можете написать представление следующим образом:

DjangoFilterBackend¶

Чтобы использовать DjangoFilterBackend , сначала установите django-filter .

Затем добавьте 'django_filters' к INSTALLED_APPS в Django:

Теперь вам следует либо добавить бэкенд фильтра в настройки:

Или добавьте бэкэнд фильтра к отдельному представлению или набору представлений.

Если вам нужна простая фильтрация на основе равенства, вы можете установить атрибут filterset_fields на представлении или наборе представлений, перечисляющий набор полей, по которым вы хотите фильтровать.

Это автоматически создаст класс FilterSet для заданных полей, и позволит вам делать такие запросы, как:

Для более сложных требований к фильтрации вы можете указать FilterSet класс, который должен использоваться представлением. Вы можете прочитать больше о FilterSet s в django-filter documentation . Также рекомендуется прочитать раздел DRF integration .

SearchFilter¶

Класс SearchFilter поддерживает простой поиск на основе одного параметра запроса и основан на Django admin’s search functionality.

При использовании просматриваемый API будет включать элемент управления SearchFilter :

Search Filter

Класс SearchFilter будет применяться только в том случае, если у представления установлен атрибут search_fields . Атрибут search_fields должен представлять собой список имен полей текстового типа в модели, например CharField или TextField .

Это позволит клиенту фильтровать элементы в списке, делая такие запросы, как:

Вы также можете выполнить связанный поиск по полю ForeignKey или ManyToManyField с помощью нотации двойного андерскора API поиска:

Для полей JSONField и HStoreField вы можете фильтровать на основе вложенных значений внутри структуры данных, используя ту же нотацию с двойным индексированием:

По умолчанию при поиске используются частичные совпадения без учета регистра. Параметр поиска может содержать несколько условий поиска, которые должны быть разделены пробелами и/или запятыми. Если используется несколько условий поиска, то объекты будут возвращены в списке только в том случае, если совпадут все указанные условия.

Поведение поиска может быть ограничено путем добавления различных символов к search_fields .

„^“ Начинается с поиска.

По умолчанию параметр поиска называется 'search' , но это может быть отменено настройкой SEARCH_PARAM .

Чтобы динамически изменять поля поиска в зависимости от содержимого запроса, можно создать подкласс SearchFilter и переопределить функцию get_search_fields() . Например, следующий подкласс будет искать по title , только если в запросе присутствует параметр запроса title_only :

Более подробную информацию см. в разделе Django documentation .

ЗаказФильтр¶

Класс OrderingFilter поддерживает простое упорядочивание результатов, управляемое параметрами запроса.

Ordering Filter

По умолчанию параметр запроса называется 'ordering' , но это можно отменить с помощью параметра ORDERING_PARAM .

Например, чтобы упорядочить пользователей по имени пользователя:

Клиент также может указать обратный порядок, добавив к имени поля префикс „-„, как показано ниже:

Также можно указать несколько порядков:

Указание того, какие поля могут быть заказаны против¶

Рекомендуется явно указать, какие поля API должен разрешить в фильтре упорядочивания. Вы можете сделать это, установив атрибут ordering_fields на представлении, как показано ниже:

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

Если вы не укажете атрибут ordering_fields на представлении, класс фильтра по умолчанию позволит пользователю фильтровать по любым читаемым полям на сериализаторе, указанном атрибутом serializer_class .

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

Указание порядка по умолчанию¶

Если в представлении установлен атрибут ordering , он будет использоваться в качестве упорядочивания по умолчанию.

Обычно вы контролируете это, устанавливая order_by в начальном наборе запросов, но использование параметра ordering в представлении позволяет вам указать упорядочивание таким образом, что оно может быть автоматически передано в качестве контекста в шаблон рендеринга. Это позволяет автоматически отображать заголовки столбцов по-разному, если они используются для упорядочивания результатов.

Атрибут ordering может быть либо строкой, либо списком/кортежем строк.

Вы также можете предоставить свой собственный общий бэкэнд фильтрации или написать устанавливаемое приложение для использования другими разработчиками.

Для этого переопределите BaseFilterBackend , и переопределите метод .filter_queryset(self, request, queryset, view) . Метод должен вернуть новый, отфильтрованный набор запросов.

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

Пример¶

Например, вам может понадобиться ограничить доступ пользователей только к созданным ими объектам.

Мы могли бы добиться такого же поведения, переопределив get_queryset() в представлениях, но использование бэкенда фильтра позволяет вам легче добавить это ограничение к нескольким представлениям или применить его ко всему API.

Настройка интерфейса¶

Общие фильтры могут также представлять интерфейс в просматриваемом API. Для этого необходимо реализовать метод to_html() , который возвращает отрисованное HTML-представление фильтра. Этот метод должен иметь следующую сигнатуру:

to_html(self, request, queryset, view)

Метод должен возвращать отрендеренную строку HTML.

Пагинация и схемы¶

Вы также можете сделать элементы управления фильтром доступными для автогенерации схемы, которую обеспечивает REST framework, реализовав метод get_schema_fields() . Этот метод должен иметь следующую сигнатуру:

Метод должен возвращать список экземпляров coreapi.Field .

Следующие пакеты сторонних производителей предоставляют дополнительные реализации фильтров.

Пакет фильтров фреймворка Django REST¶

Класс django-rest-framework-filters package работает вместе с классом DjangoFilterBackend и позволяет легко создавать фильтры по отношениям или создавать несколько типов поиска фильтра для определенного поля.

Django REST framework полный фильтр поиска слов¶

djangorestframework-word-filter разработан как альтернатива filters.SearchFilter , который будет искать полное слово в тексте, или точное совпадение.

Django URL Filter¶

django-url-filter предоставляет безопасный способ фильтрации данных через удобные для человека URL. Он работает очень похоже на сериализаторы и поля DRF в том смысле, что они могут быть вложенными, за исключением того, что они называются filtersets и filters. Это обеспечивает простой способ фильтрации связанных данных. Также эта библиотека является универсальной, поэтому ее можно использовать для фильтрации других источников данных, а не только Django QuerySet s.

drf-url-filters¶

drf-url-filter - это простое Django приложение для применения фильтров к drf ModelViewSet „s Queryset чистым, простым и настраиваемым способом. Оно также поддерживает валидацию входящих параметров запроса и их значений. Для проверки входящих параметров запроса используется красивый пакет python Voluptuous . Самое лучшее в voluptuous то, что вы можете определить свои собственные валидации в соответствии с требованиями к параметрам запроса.

Руководство по API Django REST framework (16): Фильтрация

Поведение по умолчанию общего представления списка инфраструктуры REST - это возврат всего набора запросов из диспетчера моделей. Обычно вы хотите, чтобы API ограничивал элементы, возвращаемые набором запросов.

Скрининг GenericAPIView Самый простой способ создать подкласс набора запросов - это переписать .get_queryset() метод.

Переопределение этого метода позволяет вам настраивать набор запросов, возвращаемых представлением, множеством различных способов.

Фильтр на основе текущего пользователя

Вам может потребоваться отфильтровать набор запросов, чтобы гарантировать, что возвращаются только результаты, связанные с запросами, сделанными в настоящее время аутентифицированным пользователем.

Фильтр по URL

Другой метод фильтрации может включать ограничение набора запросов на основе определенной части URL-адреса.

Например, если ваша конфигурация URL-адреса содержит такие записи:

Затем вы можете написать представление, которое возвращает набор запросов на покупку, отфильтрованный по части имени пользователя URL-адреса:

Фильтр по параметрам запроса

Последний пример фильтрации исходного набора запросов - определение исходного набора запросов на основе параметров запроса в URL-адресе.

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

Общие фильтры также могут отображаться как элементы управления HTML в доступном для просмотра API и API управления.

Настройте серверную часть фильтра

можно использовать DEFAULT_FILTER_BACKENDS настройка Глобально устанавливает бэкэнд фильтра по умолчанию. Например.

Вы также можете использовать на основе GenericAPIView Для представления класса серверная часть фильтра устанавливается на основе каждого представления или набора представлений.

Фильтрация и поиск объектов

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

Например, в соответствии с предыдущим примером и идентификатор 4675 Для продуктов следующий URL-адрес вернет соответствующий объект или ответ 404, в зависимости от того, соответствует ли данный экземпляр продукта критериям фильтра:

Перезаписать исходный набор запросов

Обратите внимание, что вы можете переписывать одновременно .get_queryset() И универсальная фильтрация, и все будет работать как положено. Например, если у продукта есть отношения «многие ко многим» с пользователями, вам может потребоваться написать представление, подобное следующему:

DjangoFilterBackend

django-filter Библиотека содержит DjangoFilterBackend Class, он поддерживает структуру REST для точной настройки фильтрации полей.

нужно использовать DjangoFilterBackend , Первая установка django-filter . Затем django_filters Добавлено в Django INSTALLED_APPS в

Теперь вы должны добавить бэкэнд фильтра в настройки:

Или добавьте серверную часть фильтра к одному представлению или набору представлений.

Если вам нужна только простая фильтрация на основе уравнений, вы можете установить ее в представлении или наборе представлений filter_fields Свойства, перечислите набор полей, которые нужно отфильтровать.

Это автоматически создаст для данного поля FilterSet Class и позволяет делать следующие запросы:

Для более сложных требований к фильтрации вы должны указать в представлении FilterSet класс. Вы можетедокументация django-filterЧитать о FilterSet Для дополнительной информации. Также предлагаю вам прочитатьDRF integration。

SearchFilter

SearchFilter Класс поддерживает простой поиск на основе одного параметра запроса и основан на функции поиска администратора Django.

При использовании доступный для просмотра API будет содержать SearchFilter Управление:

SearchFilter В классе будет только search_fields Применяется в случае набора атрибутов. search_fields Атрибут должен представлять собой список имен полей текстового типа в модели, например CharField Или TextField 。

Это позволит клиенту фильтровать элементы в списке по запросу, например:

Вы также можете использовать нотацию двойного подчеркивания API поиска для выполнения связанных поисков по ForeignKey или ManyToManyField:

По умолчанию поиск будет использовать частичные совпадения без учета регистра. Параметры поиска могут содержать несколько условий поиска, их следует разделять пробелами и / или запятыми. Если используется несколько критериев поиска, объект будет возвращен в список только в том случае, если все предоставленные критерии соответствуют.

К различным персонажам можно заранее добавить поведение поиска. search_fields Ограничить.

  • '^' соответствует начальной части.
  • '=' Точное совпадение.
  • '@' исследовать все. (В настоящее время поддерживается только серверная часть MySQL Django.)
  • Обычное соответствие "$".

По умолчанию параметры поиска называются 'search' Но это может быть SEARCH_PARAM настройка покрытия.

OrderingFilter

OrderingFilter Класс поддерживает простые параметры запроса для управления сортировкой результатов.

По умолчанию параметры запроса называются 'ordering' Но это может быть ORDERING_PARAM настройка покрытия.

Например, чтобы отсортировать пользователей по имени пользователя:

Клиент также может указать обратную сортировку, добавив '-' перед именем поля, как показано ниже:

Вы также можете указать несколько видов:

Укажите, какие поля можно сортировать

Рекомендуется явно указать, какие поля API должен разрешать в фильтре сортировки. Вы можете установить ordering_fields Свойства для этого:

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

Если вы не указали на просмотре ordering_fields Атрибут, класс фильтра позволит пользователям фильтровать по serializer_class Любое читаемое поле в классе сериализации, указанном атрибутом.

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

Укажите порядок по умолчанию

Если установлено на виде ordering Атрибут, он будет использоваться как сортировка по умолчанию.

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

ordering Атрибут может быть строкой или списком строк (кортежей).

DjangoObjectPermissionsFilter

DjangoObjectPermissionsFilter Направлен на django-guardian Используется вместе с программным пакетом, дополнительная настройка 'view' разрешение. Фильтр гарантирует, что набор запросов возвращает только те объекты, для которых у пользователя есть соответствующие права просмотра.

Если вы используете DjangoObjectPermissionsFilter , Затем вам может потребоваться добавить соответствующий класс прав доступа к объекту, чтобы пользователи могли работать с экземпляром, только если у них есть соответствующие права доступа к объекту. Самый простой способ сделать это - унаследовать DjangoObjectPermissions И для perms_map Добавление атрибута 'view' Разрешения.

Использовать DjangoObjectPermissionsFilter с участием DjangoObjectPermissions Полный пример может выглядеть следующим образом.

permissions.py:

views.py:

Вы также можете предоставить свой собственный общий серверный модуль фильтра или написать устанавливаемое приложение, которое могут использовать другие разработчики.

Для этого наследуйте BaseFilterBackend И перезаписать .filter_queryset(self, request, queryset, view) метод. Метод должен вернуть новый отфильтрованный набор запросов.

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

Дайте каштан

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

Мы можем перезаписать вид get_queryset() Чтобы добиться того же поведения, но с использованием бэкэнда фильтра, вы можете более легко добавить это ограничение к нескольким представлениям или применить его ко всему API.

Пользовательский интерфейс

Общие фильтры также могут отображать интерфейсы в доступном для просмотра API. Для этого вы должны реализовать to_html() Метод, который возвращает обработанное HTML-представление фильтра. Этот метод должен иметь следующую сигнатуру:

to_html(self, request, queryset, view)

Этот метод должен возвращать визуализированную строку HTML.

Pagination & schemas

Достигнув get_schema_fields() Method, вы также можете сделать доступным элемент управления фильтром для автоматического создания шаблонов, предоставляемых платформой REST. Этот метод должен иметь следующую сигнатуру:

Корневой QuerySet,предоставляемый Менеджером,описывает все объекты в таблице БД.Обычно,однако,необходимо выбрать только подмножество из полного набора объектов.

- документация Django

Поведение по умолчанию общих представлений списка REST-фреймворка состоит в том,чтобы вернуть весь запрос для модельного менеджера.Часто вы хотите,чтобы ваш API ограничивал элементы,возвращаемые набором.

GenericAPIView is to override the .get_queryset() method. --> Самый простой способ отфильтровать GenericAPIView для любого представления, являющегося подклассом GenericAPIView, - переопределить метод .get_queryset() .

Переопределение этого метода позволяет настраивать квартет,возвращаемый представлением,несколькими различными способами.

Фильтрация по текущему пользователю

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

Фильтрация по URL-адресу

Другой стиль фильтрации может заключаться в ограничении набора запросов на основе некоторой части URL.

Например,если в вашем конфигурационном URL-адресе содержалась запись,подобная этой:

Затем вы можете написать представление,которое возвращает запрос на покупку,отфильтрованный по части URL,содержащей имя пользователя:

Фильтрация по параметрам запроса

Последним примером фильтрации исходного запроса будет определение исходного запроса на основе параметров запроса в url.

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

Общие фильтры также могут быть представлены в качестве элементов управления HTML в браузерном API и API администратора.

Установка задних фильтров

DEFAULT_FILTER_BACKENDS setting. For example. --> Бэкэнды фильтра по умолчанию могут быть установлены глобально, используя параметр DEFAULT_FILTER_BACKENDS . Например.

GenericAPIView class-based views. --> Вы также можете установить бэкэнды фильтра для каждого представления или набора представлений, используя представления на GenericAPIView классов GenericAPIView .

Фильтрация и поиск объектов

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

4675 , the following URL would either return the corresponding object, or return a 404 response, depending on if the filtering conditions were met by the given product instance: --> Например, учитывая предыдущий пример и продукт с идентификатором 4675 , следующий URL-адрес либо возвратит соответствующий объект, либо возвратит ответ 404, в зависимости от того, были ли условия фильтрации выполнены данным экземпляром продукта:

Переопределяющий исходный запрос

.get_queryset() and generic filtering together, and everything will work as expected. For example, if Product had a many-to-many relationship with User , named purchase , you might want to write a view like this: --> Обратите внимание, что вы можете использовать как переопределенный .get_queryset() и универсальную фильтрацию, и все будет работать как положено. Например, если у Product есть отношение «многие ко многим» с User с именем « purchase , вы можете написать такое представление:

DjangoFilterBackend

django-filter library includes a DjangoFilterBackend class which supports highly customizable field filtering for REST framework. --> Библиотека django-filter включает класс DjangoFilterBackend , который поддерживает настраиваемую фильтрацию полей для среды REST.

DjangoFilterBackend , first install django-filter . Then add django_filters to Django's INSTALLED_APPS --> Чтобы использовать DjangoFilterBackend , сначала установите django-filter . Затем добавьте django_filters в INSTALLED_APPS Джанго

Теперь вы должны либо добавить бэкэнд фильтра в свои настройки:

Или добавьте бэкэнд фильтра к отдельному виду или ViewSet.

filterset_fields attribute on the view, or viewset, listing the set of fields you wish to filter against. --> Если все, что вам нужно, это простая фильтрация на основе равенства, вы можете установить атрибут filterset_fields в представлении или viewset, перечисляя набор полей, по которым вы хотите фильтровать.

FilterSet class for the given fields, and will allow you to make requests such as: --> Это автоматически создаст класс FilterSet для заданных полей и позволит вам делать такие запросы:

FilterSet class that should be used by the view. You can read more about FilterSet s in the django-filter documentation. It's also recommended that you read the section on DRF integration. --> Для более сложных требований к фильтрации вы можете указать класс FilterSet , который должен использоваться представлением. Вы можете прочитать больше о FilterSet s в документации по django-filter . Также рекомендуется прочитать раздел об интеграции DRF .

SearchFilter

SearchFilter class supports simple single query parameter based searching, and is based on the Django admin's search functionality. --> Класс SearchFilter поддерживает простой поиск по одному параметру запроса и основан на функциональности поиска администратора Django .

SearchFilter control: --> При использовании, доступный для просмотра API будет включать элемент управления SearchFilter :

SearchFilter class will only be applied if the view has a search_fields attribute set. The search_fields attribute should be a list of names of text type fields on the model, such as CharField or TextField . --> Класс SearchFilter будет применяться только в том случае, если для представления установлен атрибут search_fields . search_fields атрибут должен быть список имен полей типа текста на модели, такие как CharField или TextField .

Это позволит клиенту отфильтровывать элементы списка,делая такие запросы:

Вы также можете выполнить соответствующий поиск на ForeignKey или ManyToManyField с помощью поискового API с двойной подстановочной нотацией:

По умолчанию при поиске используются частичные совпадения без учета регистра.Параметр поиска может содержать несколько поисковых терминов,которые должны быть разделены пробелами и/или запятыми.Если используются несколько поисковых терминов,то объекты будут возвращены в список только в том случае,если все предоставленные термины совпадают.

search_fields . --> Поведение поиска может быть ограничено добавлением различных символов в search_fields .

  • ^ ^ Начинается с поиска.
  • '=' Точные совпадения.
  • '@' Полнотекстовый поиск. (В настоящее время поддерживается только серверная часть MySQL от Django.)
  • '$' Regex search.

'search' , but this may be overridden with the SEARCH_PARAM setting. --> По умолчанию параметр поиска называется 'search' , но он может быть переопределен настройкой SEARCH_PARAM .

SearchFilter and override the get_search_fields() function. For example, the following subclass will only search on title if the query parameter title_only is in the request: --> Чтобы динамически изменять поля поиска на основе содержимого запроса, можно get_search_fields() подкласс SearchFilter и переопределить функцию get_search_fields () . Например, следующий подкласс будет искать только по title если в запросе title_only параметр запроса title_only :

Для более подробной информации смотрите документацию Django .

OrderingFilter

OrderingFilter class supports simple query parameter controlled ordering of results. --> Класс OrderingFilter поддерживает простой порядок параметров, управляемый упорядочением результатов.

'ordering' , but this may by overridden with the ORDERING_PARAM setting. --> По умолчанию параметр запроса называется 'ordering' , но он может быть переопределен параметром ORDERING_PARAM .

Например,чтобы заказать пользователей по имени пользователя:

Клиент также может указывать обратные ордера,префиксовав имя поля со знаком '-':

Могут быть также указаны несколько заказов:

Указание того,по каким полям можно сделать заказ

ordering_fields attribute on the view, like so: --> Рекомендуется явно указать, какие поля должен разрешать API в фильтре упорядочения. Вы можете сделать это, установив атрибут ordering_fields в представлении, например так:

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

ordering_fields attribute on the view, the filter class will default to allowing the user to filter on any readable fields on the serializer specified by the serializer_class attribute. --> Если вы не укажете атрибут ordering_fields в представлении, класс фильтра по умолчанию разрешит пользователю фильтровать любые читаемые поля в сериализаторе, указанном атрибутом serializer_class .

'__all__' . --> Если вы уверены, что набор запросов, используемый представлением, не содержит конфиденциальных данных, вы также можете явно указать, что представление должно разрешать упорядочение для любого поля модели или агрегата '__all__' , используя специальное значение «__all__» .

Указание заказа по умолчанию

ordering attribute is set on the view, this will be used as the default ordering. --> Если в представлении установлен атрибут ordering , он будет использоваться в качестве порядка по умолчанию.

order_by on the initial queryset, but using the ordering parameter on the view allows you to specify the ordering in a way that it can then be passed automatically as context to a rendered template. This makes it possible to automatically render column headers differently if they are being used to order the results. --> Обычно вместо этого вы управляете этим, устанавливая order_by в начальном наборе запросов, но используя параметр ordering в представлении, вы можете указать упорядочение таким образом, чтобы оно могло затем автоматически передаваться в качестве контекста в отображаемый шаблон. Это позволяет автоматически отображать заголовки столбцов по-разному, если они используются для упорядочения результатов.

ordering attribute may be either a string or a list/tuple of strings. --> ordering атрибута может быть строкой или список / кортеж строк.

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

BaseFilterBackend , and override the .filter_queryset(self, request, queryset, view) method. The method should return a new, filtered queryset. --> Для этого переопределите BaseFilterBackend и переопределите метод .filter_queryset(self, request, queryset, view) . Метод должен вернуть новый отфильтрованный набор запросов.

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

Example

Например,вам может понадобиться ограничить пользователей только возможностью видеть созданные ими объекты.

get_queryset() on the views, but using a filter backend allows you to more easily add this restriction to multiple views, or to apply it across the entire API. --> Мы могли бы добиться того же поведения, переопределив get_queryset() в представлениях, но используя бэкэнд фильтра, позволяет вам легче добавить это ограничение для нескольких представлений или применить его ко всему API.

Настройка интерфейса

to_html(self, request, queryset, view)

Метод должен возвращать отрисованную HTML-строку.

Нумерация страниц и схемы

coreapi.Field instances. --> Метод должен возвращать список экземпляров coreapi.Field .

Следующие пакеты сторонних разработчиков обеспечивают дополнительную реализацию фильтров.

Фреймворк-фильтры Django REST

DjangoFilterBackend class, and allows you to easily create filters across relationships, or create multiple filter lookup types for a given field. --> Пакет django-rest-framework-filters работает вместе с классом DjangoFilterBackend и позволяет легко создавать фильтры по взаимосвязям или создавать несколько типов поиска фильтров для данного поля.

Фреймворк Django REST с полным фильтром поиска слов

filters.SearchFilter which will search full word in text, or exact match. --> Djangorestframework слово фильтр разработан в качестве альтернативы filters.SearchFilter , который будет искать полное слово в тексте, или точного соответствия.

Фильтр URL-адресов Django

QuerySet s. --> django-url-filter обеспечивает безопасный способ фильтрации данных через удобные для пользователя URL-адреса. Он работает очень похоже на сериализаторы и поля DRF в том смысле, что они могут быть вложенными, за исключением того, что они называются наборами фильтров и фильтрами. Это обеспечивает простой способ фильтрации связанных данных. Также эта библиотека общего назначения, поэтому она может использоваться для фильтрации других источников данных, а не только Django QuerySet .

drf-url-filters

ModelViewSet 's Queryset in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package Voluptuous is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements. --> drf-url-filter - это простое приложение Django для применения фильтров к ModelViewSet , Queryset и настраиваемым способом. Он также поддерживает проверки параметров входящих запросов и их значений. Красивый пакет Python Voluptuous используется для проверки параметров входящего запроса. Самое приятное в сладострастии - это то, что вы можете определить свои собственные проверки в соответствии с вашими требованиями к параметрам запроса.

Настройка фильтров в Django REST Framework

Изучение

Предварительное условие: добавление фильтрации в API — Django REST Framework [lin необходимая статья уже опубликована]

Фильтры Django упрощают фильтрацию набора запросов для получения релевантных результатов на основе значений, присвоенных полям фильтра. Но что, если пользователь хочет получить детали в пределах заданного диапазона. Скажем, например, пользователю нужно получить подробную информацию о роботах в зависимости от ценового диапазона. Здесь возникает необходимость настройки фильтров. Давайте создадим и применим настраиваемый фильтр к модели робота, чтобы пользователь мог получить сведения о роботе, указав название категории робота, название производителя, валюту, диапазон дат производства и / или ценовой диапазон.

Мы создадим новый класс с именем RobotFilter class, который является подклассом класса django_filters.FilterSet. Объявим импорт

from django_filters import FilterSet, AllValuesFilter from django_filters import DateTimeFilter, NumberFilter

Теперь вы можете добавить приведенный ниже код перед классом RobotList.

from_manufacturing_date = DateTimeFilter(field_name = 'manufacturing_date' , to_manufacturing_date = DateTimeFilter(field_name = 'manufacturing_date' , min_price = NumberFilter(field_name = 'price' , lookup_expr = 'gte' ) max_price = NumberFilter(field_name = 'price' , lookup_expr = 'lte' ) robotcategory_name = AllValuesFilter(field_name = 'robot_category__name' ) manufacturer_name = AllValuesFilter(field_name = 'manufacturer__name' )

Посмотрим на атрибуты, объявленные в классе RobotFilter.

  • from_manufacturing_date
  • to_manufacturing_date
  • min_price
  • max_price
  • robotcategory_name
  • manufacturer_name

from_manufacturing_date: это атрибут экземпляра django_filters.DateTimeFilter, который фильтрует роботов, чье значение production_date больше или равно заданному значению DateTime. Здесь, в DateTimeFilter, есть два параметра, названные field_name и lookup_expr. Поле field_name имеет дату изготовления (для фильтрации), а «gte» (больше или равно) применяется к lookup_expr.

to_manufacturing_date: это атрибут экземпляра django_filters.DateTimeFilter, который фильтрует роботов, значение production_date которых меньше или равно заданному значению DateTime. Здесь, в DateTimeFilter, есть два параметра, названные field_name и lookup_expr. В field_name мы указали дату изготовления, а lte (меньше или равно) применяется к lookup_expr.

min_price: это атрибут экземпляра django_filters.NumberFilter, который фильтрует роботов, значение цены которых больше или равно указанному значению цены.

max_price: это атрибут экземпляра django_filters.NumberFilter, который фильтрует роботов, значение цены которых меньше или равно указанному значению цены.

robotcategory_name: это атрибут экземпляра django_filters.AllValuesFilter, который фильтрует роботов, чье имя категории роботов совпадает с указанным строковым значением. Вы можете заметить, что есть двойное подчеркивание (__) стоимость, предоставленной field_name, между robot_category и именем. Поле field_name использует двойное подчеркивание Django, чтобы читать его как поле имени для модели RobotCategory. Это помогает получить подробную информацию о роботе на основе имени категории робота, а не его идентификатора pk.

Manufacturer_name: это атрибут экземпляра django_filters.AllValuesFilter, который фильтрует роботов, название производителя которых совпадает с указанным строковым значением. Поле field_name использует двойное подчеркивание Django для чтения значения «Manufacturer__name» как поля имени для модели производителя. Это помогает получить подробную информацию о роботе на основе имени производителя, а не его идентификатора ПК.

Класс RobotFilter также определяет внутренний класс Meta. Этот класс имеет две модели атрибутов и поля. Атрибут model указывает модель (робота) для фильтрации. А атрибут fields содержит имена полей и имена фильтров (в виде кортежа строк) для включения в фильтры для упомянутой модели (Robot).

Давайте использовать класс RobotFilter в нашем классе RobotList. Код следующим образом

Читайте также: