Django 및 Django Rest Framework(DRF)의 Filter 기능에 대한 간략한 정리
1. DRF - filter_backends
DRF를 이용하여 viewset을 사용하면 상속받는 ModelViewSet <- GenericViewSet <- generics.GenericView의 속성값으로 filter_backend가 있다.
이 세팅값은 프로젝트의 settings.py에서 아래처럼 설정한 DRF의 기본 filter 기능으로 작동한다.
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
"DEFAULT_RENDERER_CLASSES": [
"rest_framework.renderers.JSONRenderer",
],
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend",
],
...
기본적인 내용은 DRF docs - Filtering - Generic Filtering 부분에서 볼 수 있다.
https://www.django-rest-framework.org/api-guide/filtering/#generic-filtering
사용법
사용법은 viewset에서 filter_backends 속성에 DjangoFilterBackend를 넣어주어 사용할 수 있다.
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]
그럼 클라이언트가 쿼리파라미터로 ordering={모델의 속성값} 을 입력하면 그에 맞게 ordering이 된다.
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['name', 'created']
ordering = ['id']
여기서 ordering은 default로 지정할 정렬 속성값이다.
또한 {속성의 이름}={속성값}으로 입력 시 해당 조건으로 filtering이 지원된다.
http://example.com/api/products/4675/?category=clothing&max_price=10.00
2. 사용자 정의 필터: django-filter라이브러리 - filterset_class
DRF와 함께 작동하는 django-filter 라이브러리가 있다.
https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html
간단히는 아래와 같이 filterset_class를 지정해주어 사용할 수 있다. filters.NumberFilter가 있는데 이외에도 CharFilter, BooleanFilter등 다양한 filter들이 지원된다. 예를 들어 사용자가 ?isActive=true 라는 쿼리파라미터를 보내면 서버에서는 request.get["isActive"] = "true"라는 문자열로 받는다. 그런데 BooleanFilter값으로 적용되어있다면, 파이썬에서 사용하는 boolean 타입으로 자동으로 전환해준다.
class ProductFilter(filters.FilterSet):
min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')
class Meta:
model = Product
fields = ['category', 'in_stock']
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ProductFilter
사용자 정의 필터
좀 더 상세한 조건으로 사용자 정의 필터를 구현하고 싶다면, 아래 처럼 method를 만들고 filters의 인자값으로 넣어주면 된다.
class CustomFilter(django_filters.FilterSet):
has_bug = django_filters.BooleanFilter(method="filter_has_bug")
class Meta:
model = Fruit
fields = [
"has_bug",
]
def filter_has_bug(self, queryset, name, value):
if value:
queryset = queryset.filter(
bug__isnull=False
]
)
return queryset
'Programming-[Backend] > Django' 카테고리의 다른 글
[TIL] Django ListSerializer 활용, List Update/Create (0) | 2023.03.20 |
---|---|
[TIL] django, MYSQL, postgresql db collation (0) | 2023.02.15 |
[탐험] Django admin에서 view, template, render 다루기. 비동기 처리 버튼 만들기 (0) | 2022.12.25 |
[TIL] django data migration 데이터 마이그레이션 (0) | 2022.12.17 |
[TIL] FloatField, DecimalField 차이점 / 위경도 표시 소수점과 거리값 (0) | 2022.12.14 |