본문 바로가기
관리자

Programming-[Backend]/Django

[TIL] DjangoFilter(DRF filter_bakcends, django-filter filterset_class)

728x90
반응형

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

 

728x90
반응형