Фильтрация
Last updated
Was this helpful?
Last updated
Was this helpful?
источник:
filters.py
Корневой QuerySet, предоставляемый менеджером, описывает все объекты в таблице базы данных. Однако обычно требуется выбрать только подмножество из полного набора объектов.
—
По умолчанию общие списочные представления DRF возвращают весь QuerySet
для менеджера модели. Часто требуется, чтобы API ограничивал количество элементов, возвращаемых QuerySet
.
Простейшим способом фильтрации QuerySet
любого представления, подкласса GenericAPIView
, является переопределение метода .get_queryset()
.
Переопределение этого метода позволяет настраивать QuerySet
, возвращаемый представлением, различными способами.
Возможно, потребуется отфильтровать QuerySet
, чтобы возвращать только результаты, относящиеся к текущему аутентифицированному пользователю, сделавшему запрос.
Это можно сделать с помощью фильтрации по значению request.user
.
Например:
Другой стиль фильтрации может включать ограничение QuerySet
на основе некоторой части URL.
Например, если в конфигурации URL содержится запись следующего вида:
Затем вы можете написать представление, возвращающее QuerySet
покупок, отфильтрованный по имени пользователя в части URL:
Следующим примером фильтрации исходного QuerySet может быть определение исходного QuerySet на основе параметров запроса в url.
Мы можем переопределить .get_queryset()
для работы с такими URL, как http://example.com/api/purchases?username=denvercoder9
, и фильтровать QuerySet только в том случае, если в URL включен параметр username
:
Помимо возможности переопределения стандартного QuerySet, DRF также включает поддержку общих бэкендов фильтрации, которые позволяют легко строить сложные поисковые запросы и фильтры.
Общие фильтры также могут быть представлены в виде элементов управления HTML в API просмотра и API администрирования.
Бэкенды фильтров по умолчанию могут быть заданы глобально, с помощью параметра DEFAULT_FILTER_BACKENDS
. Например:
Вы также можете задать бэкенды фильтров для каждого вида или для каждого набора видов, используя класс GenericAPIView
, основанный на представлениях.
Обратите внимание, что если для представления настроен бэкэнд фильтрации, то он будет использоваться не только для фильтрации списочных представлений, но и для фильтрации QuerySet
, используемых для возврата одного объекта.
Например, если взять предыдущий пример и товар с идентификатором 4675
, то следующий URL будет либо возвращать соответствующий объект, либо возвращать ответ 404, в зависимости от того, были ли выполнены условия фильтрации для данного экземпляра товара:
Обратите внимание, что можно использовать и переопределенный .get_queryset()
, и общую фильтрацию, и все будет работать так, как ожидается. Например, если у Product
есть отношение "многие-ко-многим" с User
, названное purchase
, вы можете написать представление следующим образом:
Чтобы использовать DjangoFilterBackend
, сначала установите django-filter
.
Затем добавьте 'django_filters'
в INSTALLED_APPS
Django:
Теперь необходимо либо добавить бэкэнд фильтра в настройки:
Или добавить бэкэнд фильтрации в отдельный View
или ViewSet
.
Если вам нужна простая фильтрация на основе равенства, вы можете установить атрибут filterset_fields
для представления или набора представлений, перечислив набор полей, по которым вы хотите осуществлять фильтрацию.
Это автоматически создаст класс FilterSet
для заданных полей и позволит выполнять такие запросы, как:
При использовании в состав Web-интерфейса API будет входить элемент управления SearchFilter
:
Класс SearchFilter
будет применяться только в том случае, если у представления установлен атрибут search_fields
. Атрибут search_fields
должен представлять собой список имен полей текстового типа в модели, например CharField
или TextField
.
Это позволит клиенту фильтровать элементы списка, задавая такие запросы, как:
Также можно выполнить связанный поиск по полю ForeignKey
или ManyToManyField
с помощью нотации двойного подчеркивания в API поиска:
По умолчанию в поиске используются частичные совпадения без учета регистра. Параметр search
может содержать несколько условий поиска, которые должны быть разделены пробелами и/или запятыми. Если используется несколько условий поиска, то объекты будут возвращены в списке только при совпадении всех указанных условий. Поиск может содержать цитируемые фразы с пробелами, каждая фраза рассматривается как один поисковый термин.
Поведение поиска может быть задано путем добавления префикса к именам полей в search_fields
одним из следующих символов (что эквивалентно добавлению __<lookup>
к полю):
^
istartswith
Начинается с поиска.
=
iexact
Точные совпадения.
$
iregex
Regex-поиск.
@
search
None
icontains
Содержит поиск (по умолчанию).
Например:
По умолчанию параметр поиска называется 'search'
, но это можно переопределить с помощью параметра SEARCH_PARAM
.
Для динамического изменения полей поиска в зависимости от содержимого запроса можно подклассифицировать SearchFilter
и переопределить функцию get_search_fields()
. Например, следующий подкласс будет искать по title
, только если в запросе присутствует параметр запроса title_only
:
Класс OrderingFilter
поддерживает простое упорядочивание результатов, управляемое параметрами запроса.
По умолчанию параметр запроса называется 'ordering'
, но это можно переопределить с помощью параметра ORDERING_PARAM
.
Например, чтобы упорядочить пользователей по имени пользователя:
Клиент может задать и обратный порядок, добавив к имени поля префикс '-', например, так:
Также может быть задано несколько порядков:
Рекомендуется явно указывать, какие поля API должен разрешать в фильтре упорядочивания. Это можно сделать, установив атрибут ordering_fields
на представлении, например, так:
Это позволяет предотвратить непредвиденную утечку данных, например, разрешить пользователям заказывать по хэш-полю пароли или другие конфиденциальные данные.
Если не указать атрибут orderering_fields
для представления, то класс фильтра будет по умолчанию позволять пользователю фильтровать по любым читаемым полям на сериализаторе, указанном атрибутом serializer_class
.
Если вы уверены, что используемый представлением Queryset
не содержит конфиденциальных данных, вы также можете явно указать, что представление должно разрешать упорядочивание по любому полю модели или агрегату Queryset
, используя специальное значение '__all__'
.
Если у представления установлен атрибут ordering
, то он будет использоваться в качестве упорядочивания по умолчанию.
Обычно для этого используется параметр order_by
в исходном Queryset
, но использование параметра ordering
в представлении позволяет указать порядок таким образом, что он может быть автоматически передан в качестве контекста в шаблон рендеринга. Это позволяет автоматически отображать заголовки столбцов по-разному, если они используются для упорядочивания результатов.
Атрибут orderering
может быть как строкой, так и списком/кортежем строк.
Вы также можете предоставить свой собственный бэкэнд фильтрации или написать устанавливаемое приложение для использования другими разработчиками.
Для этого переопределите BaseFilterBackend
и переопределите метод .filter_queryset(self, request, queryset, view)
. Метод должен возвращать новый, отфильтрованный QuerySet
.
Помимо того, что клиенты могут выполнять поиск и фильтрацию, общие бэкенды фильтров могут быть полезны для ограничения того, какие объекты должны быть видны для каждого конкретного запроса или пользователя.
Например, может потребоваться ограничить доступ пользователей только к созданным ими объектам.
Мы могли бы добиться такого же поведения, переопределив get_queryset()
в представлениях, но использование бэкенда фильтров позволяет более просто добавить это ограничение к нескольким представлениям или применить его ко всему API.
Общие фильтры также могут представлять интерфейс в Web-интерфейсе API. Для этого необходимо реализовать метод to_html()
, который возвращает отрендеренное HTML-представление фильтра. Этот метод должен иметь следующую сигнатуру:
to_html(self, request, queryset, view)
.
Метод должен возвращать отрендеренную HTML-строку.
Следующие пакеты сторонних производителей предоставляют дополнительные реализации фильтров.
Библиотека включает класс DjangoFilterBackend
, который поддерживает высоконастраиваемую фильтрацию полей для DRF.
Для более сложных требований к фильтрации можно указать класс FilterSet
, который должен использоваться представлением. Более подробно о FilterSet
можно прочитать в . Также рекомендуется прочитать раздел .
Класс SearchFilter
поддерживает простой поиск по одному параметру запроса и основан на функциональности .
Для полей и можно осуществлять фильтрацию по вложенным значениям внутри структуры данных, используя ту же нотацию двойного подчеркивания:
Полнотекстовый поиск (в настоящее время поддерживается только бэкенд Django ).
Более подробную информацию можно найти в .
работает совместно с классом DjangoFilterBackend
и позволяет легко создавать фильтры по отношениям, а также создавать несколько типов фильтров для поиска по заданному полю.
разработан как альтернатива filters.SearchFilter
, который будет искать полное слово в тексте, либо точное совпадение.
предоставляет безопасный способ фильтрации данных по удобным для человека URL-адресам. Он работает очень похоже на сериализаторы и поля DRF в том смысле, что они могут быть вложенными, за исключением того, что они называются filtersets
и filters
. Это обеспечивает простой способ фильтрации связанных данных. Кроме того, эта библиотека является универсальной, поэтому ее можно использовать для фильтрации других источников данных, а не только Django QuerySet
.
- это простое Django-приложение для применения фильтров к Queryset
в ModelViewSet
чистым, простым и настраиваемым способом. Оно также поддерживает валидацию входящих параметров запроса и их значений. Для валидации входящих параметров запроса используется красивый python-пакет Voluptuous
. Самое приятное в Voluptuous
то, что вы можете определить свои собственные валидации в соответствии с требованиями к параметрам запроса.