티스토리 뷰
DRF Filter
기본적인 viewsets class가 다음과 같이 되어 있을 경우
class IcecreamViewSet(viewsets.ModelViewSet):
queryset = Icecream.objects.all()
serializer_class = IcecreamSerializer
/api/icecream/
으로 요청을 보내서 DB에 존재하는 icecream list를 불러오게 됩니다.
[
{
"id": 7,
"name": "메로나",
"price": 1000
},
{
"id": 8,
"name": "누가바",
"price": 1000
},
{
"id": 9,
"name": "돼지바",
"price": 1000
},
...
]
/api/icecream/7/
과 같이 요청을 보내면 해당 id값을 가진 하나의 데이터만을 불러오게 됩니다.
{
"id": 7,
"name": "메로나",
"price": 1000
}
만약 name이 메로나 인것만 찾고 싶다면?
/api/icecream/?name=메로나
와 같이 쿼리 파라미터에 name이라는 key와 메로나라는 value를 넣어줘서 요청하면 됩니다.
하지만 기본적으로는 적용되어 있지 않아서 필터링이 가능하도록 만들어줘야 합니다.
간단하게는 다음과 같이 가능합니다.
class IcecreamViewSet(viewsets.ModelViewSet):
queryset = Icecream.objects.all()
serializer_class = IcecreamSerializer
def get_queryset(self):
queryset = Icecream.objects.all()
name = self.request.query_params.get('name')
price = self.request.query_params.get('price')
if name is not None:
queryset = queryset.filter(name=name)
if price is not None:
queryset = queryset.filter(price=price)
return queryset
get_queryset
에서 쿼리파라미터로 name
과 price
가 들어올 경우 필터링된 쿼리셋을 리턴합니다.
/api/icecream/?name=메로나&price=1000
으로 GET요청을 했을경우 다음과 같이 필터링 된 결과를 볼 수 있습니다.
[
{
"id": 1,
"name": "메로나",
"price": 1000
},
{
"id": 2,
"name": "메로나",
"price": 1000
},
{
"id": 3,
"name": "메로나",
"price": 1000
},
...
DjangoFilterBackend
좀 더 세분화된 필터링을 하고싶을 경우, 그리고 좀 더 깔끔하게 만들고 싶을경우 FilterBackend
를 이용하는것이 좋습니다.
DjangoFilterBackend
을 사용하려면 먼저 django-filter
를 설치 해줘야 합니다
pip install django-filter
'django_filters' 를 INSTALLED_APPS
에 추가 해줍니다
INSTALLED_APPS = [
...
'django_filters',
...
]
다음과 같이 DjangoFilterBackend를 추가 해줍니다.
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
또는 다음과 같이 일부 viewset에 각각 적용할 수도 있습니다.
from django_filters.rest_framework import DjangoFilterBackend
class IcecreamViewSet(viewsets.ModelViewSet):
...
filter_backends = [DjangoFilterBackend]
위와 같이 설정을 마친뒤에 filterset_fields
만 넣어주면 바로 필터링이 적용된 결과값을 확인할 수 있습니다.
class IcecreamViewSet(viewsets.ModelViewSet):
queryset = Icecream.objects.all()
serializer_class = IcecreamSerializer
filterset_fields = ['name', 'price']
현재는 name
, price
필드만 필터링 가능하게 되어있고 적용하고싶은 모델의 필드명을 넣으면 됩니다. 만약 모든 필드를 적용하고 싶다면
필드 리스트 대신에‘__all__’
을 넣어주면 모든 필드가 적용됩니다.
만약 필터를 밖으로 빼서 더 깔끔하게 하고싶다면 다음과 같이 filters.py
를 만들고, 각각 모델의 필터를 클래스로 정의 해주는 방법으로도 사용이 가능합니다.
from app1.models import Icecream
import django_filters
class IcecreamFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name='name')
price = django_filters.NumberFilter(field_name='price')
class Meta:
model = Icecream
fields = '__all__'
class IcecreamViewSet(viewsets.ModelViewSet):
queryset = Icecream.objects.all()
serializer_class = IcecreamSerializer
filterset_class = IcecreamFilter # 하나만 추가
SearchFilter
문서를 보면 searchFilter도 확인해 볼 수 있습니다.
다음과 같이 두가지 속성만 넣어주면 바로 사용이 가능합니다.
filter_backends = [filters.SearchFilter]
search_fields = ['name', 'price']
127.0.0.1:8000/api/icecream/?search=메로나
와 같이 search
를 쿼리 파라미터로 넣고 검색하면
(0.003) SELECT "app1_icecream"."id", "app1_icecream"."name", "app1_icecream"."price" FROM "app1_icecream" WHERE ("app1_icecream"."name" LIKE '%메로나%' ESCAPE '\\' OR "app1_icecream"."price" LIKE '%메로나%' ESCAPE '\\'); args=('%메로나%', '%메로나%'); alias=default
위와 같은 쿼리가 이뤄집니다. LIKE query
로 name
과 price
에서 검색을 해줍니다.
만약 필드가 외래키로 연결이 되어있다면
search_fields = ['username', 'email', 'profile__profession']
과 같이 __로 연결 되어있는 모델의 속성에서까지 검색이 가능합니다.
다음과 같은 옵션들을 추가하여 검색도 가능합니다.
- '^' Starts-with search.
- '=' Exact matches.
- '@' Full-text search. (Currently only supported Django's PostgreSQL backend.)
- '$' Regex search.
그 외에 orderingFilter또한 존재합니다.
공식 사이트에서 더 자세하게 확인 가능합니다.
https://www.django-rest-framework.org/api-guide/filtering/#filtering
'DEV > Django' 카테고리의 다른 글
[Django] ValueError: I/O operation in closed file (0) | 2022.05.15 |
---|---|
[Django] SQL Lite Query 보는 방법 (0) | 2022.05.01 |
[Django] CORS 오류 (0) | 2022.04.23 |
[Django DRF] Serializer를 통한 데이터 검증 (0) | 2022.04.11 |
[Django] Gunicorn, 배포를 위한 도구 (0) | 2022.03.27 |
- Total
- Today
- Yesterday
- sql lite
- 의대 신경학 강의
- 프로그래머스
- 문자열 뒤집기
- ManyToMany
- taggit
- leetcode
- 파이썬
- 방금그곡
- query
- 팰린드롬수
- conTeXt
- for-else
- stdout
- 독후감
- django
- 백준
- 소프트웨어 장인
- dfs
- gunicorn
- Two Scoops of Django
- go
- Python
- go context
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |