Django Web Project 개발일지4) 검색 기능 추가

Mongle·2020년 7월 28일
6

DjangoBoard

목록 보기
5/7
post-thumbnail

👆 Q-객체를 이용한 검색기능 구현
이번 프로젝트에서 검색 기능은 blog앱 내의 검색으로 제한 할 것이다. 앱 내의 검색 기능은 장고 자체의 Q-객체를 이용해서 구현할 수 있다.
검색 단어를 입력받는 폼을 만들고 Q객체를 이용해서 검색 단어가 들어있는 블로그를 찾아 보여줄 것이다.
Q객체가 무엇인지는 추가적으로 알아보자.


데이터베이스를 수정할 필요가 없기 때문에 model.py, admin.py의 수정도 필요하지 않다.
검색 폼과 검색 결과를 띄워줄 url을 추가하고 view와 template을 추가해주면 된다.


🦉 1. url 설계

blog/urls.py

#/blog/search/
path('search/', views.SearchFormView.as_view(), name='search'),

url을 추가해준다. 검색 폼을 보여주고 폼에 들어있는 데이터를 처리하기 위한 뷰이므로 FormView를 상속받아 정의한다.

🦚 2. views.py 코딩

blog/forms.py

from django import forms

class PostSearchForm(forms.Form):
    search_word = forms.CharField(label='Search Word')

✍ django.forms 모듈

폼을 정의하기 위해서 django.forms 모듈의 Form클래스를 상속받아 메서드를 정의한다.
폼을 정의하는 방법은 모델클래스를 정의하는 방법과 유사하다.

<input type="text" name="search_word" label="Search Word">

를 만든 것과 동일하다.

blog/views.py

#FormView
class SearchFormView(FormView):
    form_class = PostSearchForm
    template_name = 'blog/post_search.html'

    def form_valid(self, form):
        searchWord = form.cleaned_data['search_word']
        post_list = Post.objects.filter(Q(title__icontains=searchWord) | Q(description__icontains=searchWord) | Q(content__icontains=searchWord)).distinct()

        context = {}
        context['form'] = form
        context['search_term'] = searchWord
        context['object_list'] = post_list

        return render(self.request, self.template_name, context)

👉 FormView : GET 요청인 경우 폼을 화면에 보여준다. POST 요청의 경우 데이터의 유효성 검사를 한 후, 데이터가 유효하면 form_valid()함수를 실행한 후 리다이렉트 시키는 기능을 가지고 있다.
하지만, 여기에서는 render함수로 HttpResponse객체를 반환했기 때문에 HttpResponseRedirect 처리가 되지 않았다. 즉, 리다이렉트 처리가 되지 않은 것이다.
👉 Q 객체 : filter()메서드의 조건을 다양하게 줄 수 있게 한다.
👉 icontains 연산자 : 대소문자를 구분하지 않고 단어가 포함되어 있는지 검사한다.
👉 dinstinct() 메서드 : 중복된 객체를 제외한다.

유효성 검사를 실시해 에러가 없으면 form_valid()메서드를 실행한다.
유효성 검사를 통과하면, 사용자가 입력한 데이터들은 cleaned_data 딕셔너리에서 search_word 값을 추출해 searchWord 변수에 할당한다.
필터를 거쳐 남은 post_list는 context변수 object_list에 저장한다.
그 외에도 템플릿에서 사용한 context변수를 저장하여 템플릿으로 넘겨준다.

🐧 3. template 코딩

blog/post_search.html

{% extends "base.html" %}

{% block title %}post_search.html{% endblock %}

{% block content %}
<h1>Blog Search</h1>
<br>

<form action="." method="post"> {% csrf_token %}
    {{ form.as_table }} <!-- form을 테이블 형식으로 표시, 여기서 form은 views에서 넘겨준 PostSearchForm 객체임-->
    <input type="submit" value="Submit" class="btn btn-primary btn-sm">
</form>

<br/><br/>

{% if object_list %}
    {% for post in object_list %}
        <h2><a href='{{ post.get_absolute_url }}'>{{ post.title }}</a></h2>
        {{ post.modify_date|date:"N d, Y" }}
        <p>{{ post.description }}</p>
    {% endfor %}
{% elif search_term %}<!-- 검색란이 공란인지 확인-->
    <b><i>Search Word({{ search_term }}) Not Found</i></b>
{% endif %}
{% endblock %}

views.py에서 받아온 object_list를 순회하면서 post의 제목, 수정일, 설명 등 post의 정보를 가져와 화면에 출력한다. datail url로 링크도 걸어준다.
search_term은 검색창이 공란이 아닐 경우 검색창에 입력된 값을 반환한다.

🐥 4. 검색 기능 확인하기


검색 페이지가 만들어졌다. (이쁜 화면은 아니지만 기능에 집중하자(✿◕‿◕✿))

검색어 "hi"를 입력했을 때 출력된 것이다. 글 제목과 글 내용에서 hi를 찾아서 해당 포스트를 출력해준다.

검색된 포스트가 없을 경우 NotFound를 출력한다.


✍ 마치며...

처음에 장고를 공부했을 때에는

context = {
 template에서 쓸 변수명 : 가져갈 것
}

이런 식으로 context변수를 설정했었다.
어떤게 확실히 더 편한지 아직은 잘 모르겠어서 두 가지 모두 사용하고 있다.
장고는 제공하는 기능이 다양한게 장점인데 사용하다 보니까 너무 기능이 많아서 새로운게 끊임없이 튀어나온다는 점은 장점이자 단점인 것 같다.

profile
https://github.com/Jeongseo21

1개의 댓글

comment-user-thumbnail
2021년 6월 7일

안녕하세요 친절하게 차근차근 알려주셔서 감사합니다! 많은 도움 얻고 가요
혹시 근데 위 views.py의 class SearchFormView(FormView): 이 부분에서 괄호안에 들어간 FormView가 계속 에러가 뜨는데 저 괄호안에를 어떻게 고쳐야 안뜰까요 ㅠㅠ..?

답글 달기