Old Branch

Django - tweetme 소셜서비스 구현해보기 (15) - Advanced Searching - 검색기능 적용하기

woolbro 2019. 11. 1. 02:00
반응형

안녕하세요 이번 포스팅에서는 작성 된 Tweet앱에서 내용들을 검색 해 출력 해 주는 기능을 작성 하 도록 하겠습니다.

쿼리를 하나 혹은그 이상으로 적용 해서 검색 할 수 있도록 하는 기능입니다.

 

이번 포스팅의 소스코드는 Github에 업로드 했습니다.

 


1. ListView - Search 쿼리 만들어주기

Tweet들이나 사이트에 들어있는 데이터를 검색하기 위해서는 많은 방법들이 있지만, 그 중에서 url을 사용해 검색을 해 보도록 하겠습니다.

우선 전체 리스트가 나오는 화면에서 검색을 해야겠죠?

 

Views.py에서, ListView 클래스의 코드를 아래와 같이 수정 해 주겠습니다

class TweetListView(ListView):
    
    # queryset = Tweet.objects.all()
    def get_queryset(self, *args, **kwargs):
        qs = Tweet.objects.all()
        print(self.request.GET)
        return qs

    def get_context_data(self, *args, **kwargs):
        context = super(TweetListView,self).get_context_data(*args,**kwargs)
        return context

get_queryset의 함수를 만들어서 쿼리를 그 안에 넣어주었습니다.

그리고, URL에서 사용된 파라미터들을 출력 해 주기 위해서 print(self.request.GET)을 넣어주었습니다.

동작이 어떻게 되는지 확인 해 보도록 하겠습니다.

 

일반적인 url로 접근 시 아래와 같이 print문에 Queryset 이 비어있는 채로 출력되게 됩니다.

 

이제 url parameter로 qs=needSearchTextHere 를 넣어주고 요청을 해 보겠습니다.

아래와 같이 Queryset에 qs : ["needSearchTextHere"] 이 print문에 의해 출력됩니다.

 

이제 이 쿼리를 사용 해 보도록 하겠습니다.

 

self.request.GET 을 통해 URL parameter를 가져 올 수 있다는 것을 알았으니까 ,이 것을 사용 한 후 get메서드로 해당 param을 가져와 사용하도록 하겠습니다.

 

방금 작성한 query 함수를 아래와 같이 수정 해 주도록 할게요. 

class TweetListView(ListView):  
    # queryset = Tweet.objects.all()
    def get_queryset(self, *args, **kwargs):
        qs = Tweet.objects.all()
        print(self.request.GET)
        query = self.request.GET.get("qs",None)
        if query is not None:
            qs = qs.filter(content__icontians=query)
        return qs

    def get_context_data(self, *args, **kwargs):
        context = super(TweetListView,self).get_context_data(*args,**kwargs)
        return context

 

그리고 아까와 같이 다시 시도하면, 결과가 있다면 결과를 출력 해 주고 없다면 이전에 작성했던 if문 안에 있는 Not Tweet Yet을 출력 해 줍니다.
아래는 listview의 html 파일입니다.

<h1>list_view.html</h1>
{% for obj in object_list %}
    <h2>{{ obj.content}}</h2><!-- object의 content -->
    {{ obj.user}}</br><!--object의 user-->
    {{ obj.timestamp}}</br><!--object의 timestamp-->
    {{ obj.timestamp|timesince}}</br><!--object의 timestamp로부터 지난 시간-->
    <hr>
{% empty %}
{% if request.GET.qs %}
    <p> No Tweets found</p>
{% else %}
    <p> No Tweets Yet....</p>
{% endif %}
{% endfor%}

 

 

그럼 이제, list_view.html 글자를 없애고, 검색 할 수 있는 검색창을 하나 만들어 주겠습니다.

 

tweets템플릿에 검색할 html을 하나 만들어 주세요. 저는 search_form.html 이라고 하겠습니다.

<!-- tweets/search_form.html -->
<form method='GET' action='{% url "tweet:list" %}'>
    <input type="text" name ='qs' placeholder='Search' value="{{ request.GET.qs }}"/>
    <input type="submit" value='Search'/>
<form>

그리고 작성한 html을 tweet_list..html에 넣어주겠습니다.

<!-- tweets/tweet_list.html -->
{% include "tweets/search_form.html" %}
{% for obj in object_list %}
    <h2>{{ obj.content}}</h2><!-- object의 content -->
    {{ obj.user}}</br><!--object의 user-->
    {{ obj.timestamp}}</br><!--object의 timestamp-->
    {{ obj.timestamp|timesince}}</br><!--object의 timestamp로부터 지난 시간-->
    <hr>
{% empty %}
{% if request.GET.qs %}
    <p> No Tweets found</p>
{% else %}
    <p> No Tweets Yet....</p>
{% endif %}
{% endfor%}

작성한 form을 tweet_list.html의 상단에 넣어주었으니, 이제 검색창과 트윗 리스트가 나타나는 것을 볼 수 있습니다.

 

 

2. Advanced Query - 다중쿼리 적용하기

쿼리를 하나만 적용했습니다. 

지금의 쿼리로는 텍스트만 검색 할 수 있는데요, SNS나 Tweet을 검색 할 때에 내용으로 검색 할 수도 있지만 사용자이름으로도 검색을 하기 때문에 쿼리를 좀 더 추가 해 주도록 하겠습니다.

"Django Q lookup"이라고 검색을 하면 나오는 Django Documentation 인데요, 위의 Q 모듈을 추가 해 준다면 다중 쿼리를 쉽게 작성 할 수 있도록 도와줍니다.

 

View에 적용 시켜 보도록 하겠습니다.

from django.db.models import Q

## 전체 코드는 Github에 있습니다.
## 위의 코드는 모두 같습니다.

class TweetListView(ListView):  
    # queryset = Tweet.objects.all()
    def get_queryset(self, *args, **kwargs):
        qs = Tweet.objects.all()
        print(self.request.GET)
        query = self.request.GET.get("qs",None)
        if query is not None:
            qs = qs.filter(
                Q(content__icontains=query) |
                Q(user__username__icontains=query)
                )
        return qs

    def get_context_data(self, *args, **kwargs):
        context = super(TweetListView,self).get_context_data(*args,**kwargs)
        return context

적용 시킨 View에는 Q 모듈이 추가 되었는데요, Q(someQuery) 로 감싸주어서 해당 쿼리를 실행 해 주게 합니다.

쿼리간에는 OR 연산자( ' | ' ) 를 사용해서 다중으로 연산을 할 수 있도록 해 주었습니다.

 

이제 실행 한 서버에 들어 가 보면, 트윗 내용, 사용자 이름으로 검색했을 때 검색 결과가 잘 나오는 것을 확인 할 수 있습니다!!