Официальная оригинальная ссылка
Эта серия статей адрес github
Пожалуйста, укажите источник
фильтр
Поведение по умолчанию общих представлений списка платформы REST заключается в том, чтобы вернуть весь набор запросов из диспетчера моделей. Часто вам нужно, чтобы API ограничивал элементы, возвращаемые набором запросов.
фильтрGenericAPIView
Самый простой способ создать подкласс набора запросов — переопределить.get_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
Другой способ фильтрации может заключаться в ограничении набора запросов на основе части URL-адреса.
Например, если ваша конфигурация URL-адреса содержит такую запись:
url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()),
Затем вы можете написать представление, которое возвращает набор запросов о покупках, отфильтрованных по имени пользователя в URL-адресе:
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases for
the user as determined by the username portion of the URL.
"""
username = self.kwargs['username']
return Purchase.objects.filter(purchaser__username=username)
Фильтр по параметрам запроса
Последний пример фильтрации исходного набора запросов — определение исходного набора запросов на основе параметров запроса в URL-адресе.
мы можем покрыть.get_queryset()
обращаться с такими вещами, какhttp://example.com/api/purchases?username=denvercoder9
URL, и только если URL содержитusername
Набор запросов фильтруется только в том случае, если параметр:
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
Optionally restricts the returned purchases to a given user,
by filtering against a `username` query parameter in the URL.
"""
queryset = Purchase.objects.all()
username = self.request.query_params.get('username', None)
if username is not None:
queryset = queryset.filter(purchaser__username=username)
return queryset
Универсальный фильтр
В дополнение к возможности переопределить набор запросов по умолчанию, среда REST также включает поддержку универсальной серверной части фильтрации, что позволяет легко создавать сложные поиски и фильтры.
Общие фильтры также могут отображать себя как элементы управления HTML в доступном для просмотра API и API администратора.
установить серверную часть фильтра
можно использоватьDEFAULT_FILTER_BACKENDS
настройка Глобально устанавливает серверную часть фильтра по умолчанию. Например.
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
Вы также можете использоватьGenericAPIView
Представление класса, которое устанавливает серверную часть фильтра для каждого представления или набора представлений.
import django_filters.rest_framework
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
Фильтрация и поиск объектов
Обратите внимание, что если представление настроено с фильтрующей серверной частью, помимо фильтрации представления списка, оно также будет использоваться для фильтрации наборов запросов, которые возвращают один объект.
Например, согласно предыдущему примеру и идентификатор4675
, следующий URL-адрес вернет соответствующий объект или ответ 404, в зависимости от того, соответствует ли данный экземпляр продукта критериям фильтра:
http://example.com/api/products/4675/?category=clothing&max_price=10.00
Переопределить исходный набор запросов
Обратите внимание, что вы можете переопределить оба.get_queryset()
и общую фильтрацию, и все будет работать как положено. Например, если продукты имеют отношения «многие ко многим» с пользователями, вы можете написать представление, которое выглядит следующим образом:
class PurchasedProductsList(generics.ListAPIView):
"""
Return a list of all the products that the authenticated
user has ever purchased, with optional filtering.
"""
model = Product
serializer_class = ProductSerializer
filter_class = ProductFilter
def get_queryset(self):
user = self.request.user
return user.purchase_set.all()
Справочник по API
DjangoFilterBackend
django-filter
Библиотека содержитDjangoFilterBackend
Класс, который позволяет платформе REST настраивать фильтрацию полей.
нужно использоватьDjangoFilterBackend
, первая установкаdjango-filter
. потомdjango_filters
добавлено в ДжангоINSTALLED_APPS
середина
pip install django-filter
Теперь вы должны добавить бэкенд фильтра в настройки:
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
Или добавьте серверные части фильтра к одному представлению или набору представлений.
from django_filters.rest_framework import DjangoFilterBackend
class UserListView(generics.ListAPIView):
...
filter_backends = (DjangoFilterBackend,)
Если вам просто нужна простая фильтрация на основе уравнений, вы можете установить ее в представлении или наборе представлений.filter_fields
свойство, в котором перечислены наборы полей, по которым вы хотите отфильтровать.
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (DjangoFilterBackend,)
filter_fields = ('category', 'in_stock')
Это автоматически создастFilterSet
class и позволяет вам делать такие запросы, как:
http://example.com/api/products?category=clothing&in_stock=True
Для более сложных требований к фильтрации вы должны указать в представленииFilterSet
своего рода. ты сможешьдокументация по django-фильтручитать оFilterSet
Чтобы получить больше информации. Также рекомендуем прочитатьDRF integration.
SearchFilter
SearchFilter
Класс поддерживает простой поиск на основе одного параметра запроса и основан на возможностях поиска администратора Django.
При использовании доступный для просмотра API будет содержатьSearchFilter
Элементы управления:
SearchFilter
Класс будет работать, только если представление имеетsearch_fields
Применяется в случае набора свойств.search_fields
Свойства должны быть списком имен полей текстового типа в модели, например.CharField
илиTextField
.
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('username', 'email')
Это позволит клиентам фильтровать элементы в списке, запрашивая, например:
http://example.com/api/users?search=russell
Вы также можете выполнить связанный поиск для ForeignKey или ManyToManyField, используя нотацию двойного подчеркивания API поиска:
search_fields = ('username', 'email', 'profile__profession')
По умолчанию поиск будет использовать частичные совпадения без учета регистра. Параметры поиска могут содержать несколько условий поиска, которые должны быть разделены пробелами и/или запятыми. Если используется несколько критериев поиска, объекты будут возвращены в список только в том случае, если все предоставленные критерии совпадают.
Поведение при поиске может быть достигнуто добавлением различных символов передsearch_fields
ограничить.
- '^' соответствует начальной части.
- '=' точно соответствует.
- '@' исследовать все. (В настоящее время поддерживается только серверная часть MySQL для Django.)
- '$' Обычное совпадение.
Например:
search_fields = ('=username', '=email')
По умолчанию параметры поиска называются'search'
, но это может бытьSEARCH_PARAM
настройка переопределения.
Подробнее см.Документация Джанго.
OrderingFilter
OrderingFilter
Класс поддерживает простые параметры запроса для управления порядком результатов.
По умолчанию параметры запроса называются'ordering'
, но это может бытьORDERING_PARAM
настройка переопределения.
Например, чтобы отсортировать пользователей по имени пользователя:
http://example.com/api/users?ordering=username
Клиенты также могут указывать обратный порядок, добавляя к имени поля префикс «-», как показано ниже:
http://example.com/api/users?ordering=-username
Также можно указать несколько видов:
http://example.com/api/users?ordering=account,username
Указывает, какие поля можно сортировать по
Рекомендуется явно указать, какие поля API должен разрешать в фильтрах сортировки. Вы можете сделать это, установивordering_fields
сделать это следующим образом:
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
Это помогает предотвратить случайную утечку данных, например позволяя пользователям сортировать на основе хэш-полей паролей или других конфиденциальных данных.
Если вы не укажете в представленииordering_fields
атрибут, класс фильтра по умолчанию позволит пользователям фильтровать поserializer_class
Любые доступные для чтения поля в сериализованном классе, указанном свойством.
Если вы уверены, что набор запросов, используемый представлением, не содержит конфиденциальных данных, вы также можете использовать специальное значение'__all__'
Явное указание представления позволяет выполнять сортировку по любому полю модели или агрегату набора запросов.
class BookingsListView(generics.ListAPIView):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = '__all__'
Укажите порядок по умолчанию
Если установлено в представленииordering
свойство, оно будет использоваться как порядок по умолчанию.
Обычно вы должны сделать это, установив в начальном наборе запросовorder_by
контролировать это, но с помощьюordering
можно указать метод упорядочения, который затем может быть автоматически передан в качестве контекста отображаемому шаблону. Это может автоматически отображать заголовки столбцов, если они используются для сортировки результатов.
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('username', 'email')
ordering = ('username',)
ordering
Свойство может быть строкой или списком (кортежем) строк.
DjangoObjectPermissionsFilter
DjangoObjectPermissionsFilter
направленный наdjango-guardian
Пакеты используются вместе с дополнительной настройкой'view'
разрешение. Фильтр гарантирует, что набор запросов возвращает только те объекты, для просмотра которых у пользователя есть соответствующие права.
если вы используетеDjangoObjectPermissionsFilter
, то вам также может понадобиться добавить соответствующие классы разрешений для объектов, чтобы пользователи могли работать с экземпляром только в том случае, если у них есть соответствующие разрешения на объекты. Самый простой способ сделать это - наследоватьDjangoObjectPermissions
и дляperms_map
атрибут добавлен'view'
разрешения.
использоватьDjangoObjectPermissionsFilter
иDjangoObjectPermissions
Полный пример может выглядеть так.
permissions.py:
class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
views.py:
class EventViewSet(viewsets.ModelViewSet):
"""
Viewset that only lists events if user has 'view' permissions, and only
allows operations on individual events if user has appropriate 'view', 'add',
'change' or 'delete' permissions.
"""
queryset = Event.objects.all()
serializer_class = EventSerializer
filter_backends = (filters.DjangoObjectPermissionsFilter,)
permission_classes = (myapp.permissions.CustomObjectPermissions,)
Пользовательский общий фильтр
Вы также можете предоставить свой собственный базовый фильтр или написать устанавливаемое приложение, которое могут использовать другие разработчики.
Для этого наследуйтеBaseFilterBackend
, и перезаписать.filter_queryset(self, request, queryset, view)
метод. Метод должен возвращать новый отфильтрованный набор запросов.
В дополнение к предоставлению клиентам возможности выполнять поиск и фильтрацию, базовая часть общего фильтра может использоваться для ограничения того, какие объекты должны быть видны для данного запроса или пользователя.
взять каштан
Вы можете разрешить пользователям видеть только созданные ими объекты.
class IsOwnerFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see their own objects.
"""
def filter_queryset(self, request, queryset, view):
return queryset.filter(owner=request.user)
Мы можем сделать это, переопределивget_queryset()
для достижения того же поведения, но использование бэкенда фильтра позволяет вам более легко добавить это ограничение к нескольким представлениям или применить его ко всему API.
настраиваемый интерфейс
Общие фильтры также могут отображать интерфейсы в доступном для просмотра API. Для этого следует реализоватьto_html()
метод, возвращающий обработанное HTML-представление фильтра. Этот метод должен иметь следующую подпись:
to_html(self, request, queryset, view)
Метод должен возвращать отображаемую строку HTML.
Pagination & schemas
путем реализацииget_schema_fields()
метод, вы также можете сделать элементы управления фильтрами доступными для автоматического создания схемы, предоставляемой инфраструктурой REST. Этот метод должен иметь следующую подпись:
get_schema_fields(self, view)
Метод должен возвращатьcoreapi.Field
Список экземпляров.