Skip to content
This repository was archived by the owner on Jul 2, 2024. It is now read-only.

Commit 16d40ef

Browse files
Add filters to DRF
1 parent be37045 commit 16d40ef

File tree

1 file changed

+138
-3
lines changed

1 file changed

+138
-3
lines changed

lesson39.md

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Урок 39. REST Аутентификация, Авторизация, Permissions.
1+
# Урок 39. REST Аутентификация, Авторизация, Permissions, Фильтрация.
22

33
![](https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQ_cLOesie903fmPPbl2YbqawKsycva_owf6Q&usqp=CAU)
44

@@ -377,7 +377,7 @@ from rest_framework import viewsets
377377
class UserViewSet(viewsets.ViewSet):
378378

379379
# Cache requested url for each user for 2 hours
380-
@method_decorator(cache_page(60*60*2))
380+
@method_decorator(cache_page(60 * 60 * 2))
381381
@method_decorator(vary_on_cookie)
382382
def list(self, request, format=None):
383383
content = {
@@ -389,14 +389,15 @@ class UserViewSet(viewsets.ViewSet):
389389
class PostView(APIView):
390390

391391
# Cache page for the requested url
392-
@method_decorator(cache_page(60*60*2))
392+
@method_decorator(cache_page(60 * 60 * 2))
393393
def get(self, request, format=None):
394394
content = {
395395
'title': 'Post title',
396396
'body': 'Post content'
397397
}
398398
return Response(content)
399399
```
400+
400401
`cache_page` декоратор кеширует только `GET` и `HEAD` запросы, со статусом 200.
401402

402403
### Пример использования авторизации в ресурсах
@@ -412,6 +413,138 @@ class SomeModelViewSet(ModelViewSet):
412413

413414
Таким образом мы можем добавлять объект юзера при сохранении нашего сериалайзера.
414415

416+
## Фильтрация
417+
418+
DRF предоставляет нам огромные возможности для фильтрации, практически не дописывая для этого специальный код.
419+
420+
### SearchFilter
421+
422+
Как и с другими параметрами у нас есть два варианта указания фильтрации, общая для всего проекта, или конкретная для
423+
определённого класса или функции
424+
425+
Для указания общего фильтра на весь проект, необходимо добавить в `settings.py`, в переменную `REST_FRAMEWORK`:
426+
427+
```python
428+
REST_FRAMEWORK = {
429+
...
430+
'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter']
431+
}
432+
```
433+
434+
Для указания в конкретном классе необходимо использовать аргумент `filter_backends`. Принимает коллекцию из фильтров,
435+
например:
436+
437+
```python
438+
from rest_framework.filters import SearchFilter, OrderingFilter
439+
440+
441+
class GroupViewSet(ModelViewSet):
442+
queryset = Group.objects.all()
443+
filter_backends = [SearchFilter, OrderingFilter]
444+
445+
```
446+
447+
Или же соответсвующий декоратор, для использования в функциях
448+
449+
#### Как пользоваться?
450+
451+
Для использования необходимо добавить в класс параметр `search_fields`
452+
453+
```python
454+
class GroupViewSet(ModelViewSet):
455+
queryset = Group.objects.all()
456+
filter_backends = [SearchFilter, OrderingFilter]
457+
search_fields = ['name', 'label']
458+
```
459+
460+
Который так же принимает коллекцию, состоящую из списка полей по которым необходимо производить поиск.
461+
462+
Теперь у нас есть возможность добавить квери параметр `search=` (ключевое слово можно поменять через `settings.py`, что
463+
бы искать по указанным полям.
464+
465+
Например:
466+
467+
```
468+
http://127.0.0.1:9000/api/group/?search=Pyt
469+
```
470+
471+
Результат будет отфильтрован так, что бы отобразить только те данные, у которых хотя бы в одном из указанных полей будет
472+
найдено частичное совпадение, без учёта регистра (lookup icontains).
473+
474+
Если нам необходим более специфический параметр поиска, существует 4 специальных настройки в параметре `search_fields`:
475+
476+
- `^` Поиск только в начале строки
477+
- `=` Полное совпадение
478+
- `@` Поиск по полному тексту (работает на основе индексов, работает только для postgres)
479+
- `$` Поиск регулярного выражения
480+
481+
Например:
482+
483+
```python
484+
class GroupViewSet(ModelViewSet):
485+
queryset = Group.objects.all()
486+
filter_backends = [SearchFilter, OrderingFilter]
487+
search_fields = ['=name', '^label']
488+
```
489+
490+
### OrderingFilter
491+
492+
Точно так же можно добавить ордеринг фильтр, для того, что бы указывать ордеринг в момент запроса через квери
493+
параметр `ordering=` (так же можно заменить через `settings.py`)
494+
495+
Необходимо указать параметр `ordering_fields`, так же принимает коллекцию из полей. Так же может принимать специальное
496+
значение `__all__`, для возможности сортировать по любому полю.
497+
498+
```python
499+
class GroupViewSet(ModelViewSet):
500+
queryset = Group.objects.all()
501+
filter_backends = [SearchFilter, OrderingFilter]
502+
ordering_fields = ['name', 'label']
503+
```
504+
505+
В квери параметре может принимать символ `-`, или список полей через запятую.
506+
507+
Примеры:
508+
509+
```
510+
http://example.com/api/users?ordering=username
511+
512+
http://example.com/api/users?ordering=-username
513+
514+
http://example.com/api/users?ordering=account,username
515+
```
516+
517+
### Свой собственный фильтр
518+
519+
Как и со всем остальным можно написать свой собственный фильтр, для этого необходимо наследоваться от `rest_framework.filters.BaseFilterBackend`
520+
521+
И описать один метод `filter_queryset`, в котором можно описать любую логику.
522+
523+
Например, фильтр, который будет отображать только те объекты, которые принадлежат юзеру.
524+
525+
```python
526+
class IsOwnerFilterBackend(filters.BaseFilterBackend):
527+
"""
528+
Filter that only allows users to see their own objects.
529+
"""
530+
def filter_queryset(self, request, queryset, view):
531+
return queryset.filter(owner=request.user)
532+
```
533+
534+
## Сложные комплексные фильтры
535+
536+
На самом деле бываю и значительно более сложные фильтры, для которых существуют специальные пекеджи.
537+
538+
Например:
539+
540+
```
541+
pip install django-filter
542+
pip install djangorestframework-filters
543+
pip install djangorestframework-word-filter
544+
```
545+
546+
Все они легко настраиваются и значительно расширяют возможность использования фильтров. Изучите их самостоятельно.
547+
415548

416549
## Практика
417550

@@ -422,3 +555,5 @@ class SomeModelViewSet(ModelViewSet):
422555
3. Пишем вьюсеты для моделей из модуля, и создаём 2 покупки и 1 возврат, через постман.
423556

424557
4. Пишем собственный токен, который перестаёт действовать через 10 минут.
558+
559+
5. Добавляем фильтр, для поиска только для своих покупок если запрос от обычного пользователя, и все если администратор

0 commit comments

Comments
 (0)