본문 바로가기

web/Django_rest_framework

7 search

이번 포스팅은 search에 대한 전반적인 로직을 포스팅할 예정입니다. 


1. 먼저 로그인한 유저의 데이터만 볼수 있도록 list 부분을 수정해 보도록 하겠습니다. 


현재 저장된 데이터는 아래 화면처럼 4개 입니다. 3개는 1번인 admin  / 1개는 3번인 testuser 입니다. 




2. post/api/views.py 에서 PostListAPIView()에 get_queryset()을 오버라이딩 합니다. 


get_queryset()은 GeneriView에서 어떤 데이터를 가져올 것인지에 대한 query를 총괄하는 함수 입니다. 

기존에 사용하던 queryset이 바로 get_queryset 라고 보시면 됩니다. 

파라미터중 self.request 를 통해서 파라미터를 받아서 처리하게끔 하면 됩니다. 

자세한 사항은 아래의 링크를 참조하세요.

http://www.django-rest-framework.org/api-guide/generic-views/#get_querysetself 


이번에는 로그인한 유저의 데이터만을 가져오므로 filter()를 사용해서 user를 매칭시켜 줍니다. 


class PostListAPIView(ListAPIView):
serializer_class = PostSerializer

def get_queryset(self, *args, **kwargs):
queryset_list = Post.objects.filter(user=self.request.user)

return queryset_list


3. 다시 /api/posts/를 보시면 해당 유저의 데이터 리스트만을 리턴해 줍니다. 



4. 이번에는 url파라미터로 q값을 받아서 q와 매칭되는 데이터만을 가져오는것을 해보겠습니다. 

q로 매칭될 데이터들은 title / content / 유저 이름 으로 해보겠습니다. 

filter()의 Q()의 like인 __icontains를 써서 아래와 같이 쿼리를 짰습니다. 그리고 마지막에 .distinct()함수를 통해서 중복을 제거해 줍니다.


from django.db.models import Q
class PostListAPIView(ListAPIView):
serializer_class = PostSerializer

def get_queryset(self, *args, **kwargs):
queryset_list = Post.objects.all()
query = self.request.GET.get("q")
if query:
queryset_list = queryset_list.filter(
Q(title__icontains=query) |
Q(content__icontains=query) |
Q(user__first_name__icontains=query) |
Q(user__last_name__icontains=query)
).distinct()
return queryset_list


5. 이번의 주소는 /api/posts/?q=포스트   입니다. 

타이틀이 포스트이거나 본문 내용이 포스트 이거나 유저 이름이 포스트가 되는 데이터들은 모두 가져오는 거죠. 쉽죠?!



6. 아직 유저 이름은 넣어주지 않았으므로 /admin/에서 user 변경으로 들어갑니다. 


7. 저의 경우 admin유저의 이름을 admin admin 으로 수정하였습니다. 



8. 다시 /api/posts/?q=admin 으로 하면 아래와 같이 admin 유저의 데이터 리스트를 보여줍니다. 




9. 이번엔 쿼리가 아닌 rest_framework.filters 에서 제공하는 search를 구현해 보겠습니다. 

먼저 아래의 searchFilter 과 OrderingFilter를 import합니다. 

그리고 PostListAPIView()에 filter_backends[]와 search_fields[]를 선언해 줍니다. 


filter_backends는 사용할 필터의 정의를 search_fields는 필터링할 컬럼을 정의합니다. 

해당 컬럼은 당연히 시리얼라이져에 정의된 필드를 기준으로 합니다. 

자세한 사항은 아래의 링크를 참조하시면 됩니다. 

http://www.django-rest-framework.org/api-guide/generic-views/#filter_querysetself-queryset

from rest_framework.filters import SearchFilter, OrderingFilter



class PostListAPIView(ListAPIView):
serializer_class = PostListSerializer
filter_backends = [SearchFilter, OrderingFilter]
search_fields = ['title', 'content']

def get_queryset(self, *args, **kwargs):
queryset_list = Post.objects.all()
query = self.request.GET.get("q")
if query:
queryset_list = queryset_list.filter(
Q(title__icontains=query) |
Q(content__icontains=query) |
Q(user__first_name__icontains=query) |
Q(user__last_name__icontains=query)
).distinct()
return queryset_list



10. 단지 두줄만 추가 했을뿐인데 작동하니는지 볼까요?

/api/posts/?search=포스트 로 접속해보면 포스트가 저장된 데이터들만 뽑아 오는것을 볼수 있습니다!!


11. 여기에 아까 로직을 만들었던 q도 같이 써보면

/api/posts/?search=저장&q=admin 으로 한다면

admin유저의 포스트중 저장이라고 된 포스트만을 가져오게 됩니다. 


12. 이번엔 ordering 차례 입니다. 

/api/posts/?ordering=pk 로 하시면 pk 내림 차순으로 리턴된것을 볼수 있습니다. 



13. 오름 차순은 -만 붙여주시면 됩니다. 

/api/posts/?ordering=-pk






'web > Django_rest_framework' 카테고리의 다른 글

9. href  (0) 2016.07.30
8 pagination  (0) 2016.07.29
6 저장/수정시 유저 저장  (0) 2016.07.27
5. create  (0) 2016.07.27
4 update delete  (0) 2016.07.25