Фильтрация


источник:

  • filters.py


Фильтрация

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

Django documentationarrow-up-right

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

Простейшим способом фильтрации QuerySet любого представления, подкласса GenericAPIView, является переопределение метода .get_queryset().

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

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

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

Это можно сделать с помощью фильтрации по значению request.user.

Например:

from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer

    def get_queryset(self):
        """
        This view should return a list of all the purchases
        for the currently authenticated user.
        """
        user = self.request.user
        return Purchase.objects.filter(purchaser=user)

Фильтрация по URL

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

Переопределение исходного QuerySet

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


Руководство по API

DjangoFilterBackend

Библиотека django-filterarrow-up-right включает класс DjangoFilterBackend, который поддерживает высоконастраиваемую фильтрацию полей для DRF.

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

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

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

Или добавить бэкэнд фильтрации в отдельный View или ViewSet.

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

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

Для более сложных требований к фильтрации можно указать класс FilterSet, который должен использоваться представлением. Более подробно о FilterSet можно прочитать в документации django-filterarrow-up-right. Также рекомендуется прочитать раздел Интеграция DRFarrow-up-right.

SearchFilter

Класс SearchFilter поддерживает простой поиск по одному параметру запроса и основан на функциональности поиска в админ-панели Djangoarrow-up-right.

При использовании в состав Web-интерфейса API будет входить элемент управления SearchFilter:

Фильтр поиска

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

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

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

Для полей JSONFieldarrow-up-right и HStoreFieldarrow-up-right можно осуществлять фильтрацию по вложенным значениям внутри структуры данных, используя ту же нотацию двойного подчеркивания:

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

Поведение поиска может быть задано путем добавления префикса к именам полей в search_fields одним из следующих символов (что эквивалентно добавлению __<lookup> к полю):

Префикс
Поиск

^

istartswith

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

=

iexact

Точные совпадения.

$

iregex

Regex-поиск.

@

search

Полнотекстовый поиск (в настоящее время поддерживается только бэкенд Django PostgreSQLarrow-up-right).

None

icontains

Содержит поиск (по умолчанию).

Например:

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

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

Более подробную информацию можно найти в документации Djangoarrow-up-right.


OrderingFilter

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

Ordering Filter

По умолчанию параметр запроса называется '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-строку.

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

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

Django-rest-framework-filters

django-rest-framework-filtersarrow-up-right работает совместно с классом DjangoFilterBackend и позволяет легко создавать фильтры по отношениям, а также создавать несколько типов фильтров для поиска по заданному полю.

Djangorestframework-word-filter

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

Django-url-filter

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

drf-url-filters

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

Last updated

Was this helpful?