[REAL Python – Django] – “Django – Search 구현”

[REAL Python – Django] – “Django – Search 구현”

4월 9, 2022

JavaScript 작업하기

백엔드를 처리하기 전, 자바스크립트로 검색창에 검색어를 입력하고 엔터나 버튼을 누르면, /blog/search/검색어 로 이동하게끔 하는 코드를 작성해 주었습니다.

<script>
    function searchPost() {
        let searchValue = document.getElementById('search-input').value.trim();
        if (searchValue.length > 1) {
            location.href = "/blog/search/" + searchValue + "/";
        } else {
            alert('검색어(' + searchValue + ')가 너무 짧습니다.');
        }
    };

    document.getElementById('search-input').addEventListener('keyup', function(event)
    {
        if(event.key === 'Enter'){
            searchPost();
        }
    });
</script>

이 부분은 검색 HTML 코드입니다. 버튼이 클릭되었을 때에 searchPost() 함수가 호출되게끔 작성되어 있죠? 함수는 아래와 같이 작성되어 있습니다. id=search-input 인 것을 가져와서 그 값을 searchValue 에 담도록 되어 있습니다.

그리고 검색어를 입력하면 지정된 링크로 이동하도록 되어 있습니다. location.href = "/blog/search/" + searchValue + "/";

예컨대 검색창에 ‘자바스크립트’ 를 검색하고 엔터를 누른다면 "/blog/search/자바스크립트/" 로 이동할 겁니다. 이제 urls.py에 해당 패턴을 추가해 주고, 그것을 view에서 어떻게 처리할 것인지를 구현해 주면 됩니다.

urls.py 수정

/blog/search/사용자가 입력한 검색어/ 까지 이동하는 것은 성공했습니다. 이제 urls.py를 작업할 겁니다.

path('search/<str:q>/', views.PostSearch.as_view()),

urls.py에 해당 코드를 추가해줍니다. 'search/<str:q>/' 는 사용자가 입력한 검색어를 str로 받아 q에 저장하겠다는 의미이고, views.PostSearch.as_viewviews.py PostSearch 클래스에서 그것을 처리하겠다는 의미입니다.

views.py 작성, 핵심은 원하는 글만 가져오는 것

포스트 전체 리스트를 보여주는 것 VS 검색어에 대한 포스트 리스트를 보여주는 것 의 차이는 “검색어에 대한” 뿐 리스트를 보여주는 것 자체는 똑같습니다. 모델도 포스트로 아예 같네요.

class PostSearch(PostList):

    def get_queryset(self):
        q = self.kwargs['q']
        post_list = Post.objects.filter(
            Q(title__contains=q) | Q(tags__name__contains=q)
        ).distinct()
        return post_list

    def get_context_data(self, **kwargs):
        context = super(PostSearch, self).get_context_data()
        q = self.kwargs['q']
        context['search_info'] = f'Search: {q} ({self.get_queryset().count()})'

        return context

위에서 만든 클래스를 상속받고 두 가지 메소드를 재정의했습니다. get_queryset 메소드와 get_context_data 메소드는 각각 어떤 메소드일까요?

1. get_queryset : 데이터베이스에서 객체 받아오기

Returns the queryset that will be used to retrieve the object that this view will display. By default, get_queryset() returns the value of the queryset attribute if it is set, otherwise it constructs a QuerySet by calling the all() method on the model attribute’s default manager.

https://docs.djangoproject.com/en/4.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_queryset

get_queryset은 간단히(?) 말하면 뷰에서 처리할 쿼리셋(데이터베이스에서 받아온 객체들의 목록) 을 받아오는 메서드입니다. 그렇기 때문에 urls.py에서 얻어온 q(사용자가 입력한 검색어) 를 받아온 다음,

Q(title__contains=q) | Q(tags__name__contains=q) 코드로 원하는 데이터만 뽑아서(제목에 검색어가 들어가 있는 것과 태그이름에 검색어가 들어가있는 것) 가져오는 쿼리를 실행한 것입니다. 최종 메서드의 결과로는 뽑아온 것을 리턴하도록 되어 있습니다.

2. get_context_data : context 받아오기

Returns context data for displaying the object.

https://docs.djangoproject.com/en/4.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_data

객체를 보여주도록 하는 context 데이터를 받아온다고 적혀져 있습니다. 그런데 과연 context란 무엇일까요?

{'categories': <QuerySet []>,
 'is_paginated': True,
 'no_category_post_count': 7,
 'object_list': <QuerySet [<Post: [7] hajydb :: goddessana>, <Post: [6] stgshydj :: goddessana>, <Post: [5] afdsfasdgtht :: goddessana>, <Post: [4] qreqwerqwerq :: goddessana>]>,
 'page_obj': <Page 1 of 2>,
 'paginator': <django.core.paginator.Paginator object at 0x10cac2230>,
 'post_list': <QuerySet [<Post: [7] hajydb :: goddessana>, <Post: [6] stgshydj :: goddessana>, <Post: [5] afdsfasdgtht :: goddessana>, <Post: [4] qreqwerqwerq :: goddessana>]>,
 'view': <blog.views.PostList object at 0x10cac2560>}

예컨대 이것은 실제 프로젝트에서 /blog/ 로 접속했을 때에 context 데이터를 콘솔에 출력한 것입니다.

결론부터 말하자면 context 는 템플릿에서 쓰이는 변수명과 파이썬 객체를 연결해주는 사전형 값을 의미합니다. 그렇기 때문에 {% if post_list.exists %} 와 같은 코드를 템플릿에서 사용할 수 있는 것이죠. 위의 코드에서는 Search:사용자가입력한검색어(검색결과수) 를 템플릿에서 사용할 수 있도록 작성되어 있다는 것을 알 수 있을 것입니다. 저는 위의 코드를 템플릿에 추가해주었습니다.

의도했던 대로 결과가 잘 나타나는 것을 확인할 수 있습니다.

Leave A Comment

Avada Programmer

Hello! We are a group of skilled developers and programmers.

Hello! We are a group of skilled developers and programmers.

We have experience in working with different platforms, systems, and devices to create products that are compatible and accessible.