장고:검색기능

학교의 모든 지식. SMwiki
Sam (토론 | 기여)님의 2020년 12월 7일 (월) 22:26 판 (→‎정렬기능)
둘러보기로 이동 검색으로 이동

장고! 웹 프레임워크! 틀:장고

  1. 장고:개요
  2. 장고:웹페이지설계
    1. 장고:앱
    2. 장고:url
    3. 장고:model
      1. 장고:DB
      2. 장고:모델 필드
      3. 장고:모델의 변경
    4. 장고:view
      1. 장고:클래스형 뷰, 제네릭 뷰
      2. 장고:view 각종 기능
    5. 장고:template
    6. 장고:static. 정적파일 사용하기
      1. 장고:CSS 사용하기
      2. 장고:JS 사용하기
      3. 장고:글꼴 사용
      4. 장고:부트스트랩
    7. 장고:media. 미디어 파일 사용하기
  3. 장고:관리자페이지
  4. 장고:settings.py
  5. 장고:기능구현
    1. 장고:회원관리
    2. 장고:유저
    3. 장고:커스텀 유저
    4. 장고:소셜로그인
    5. 장고:입력받기
    6. 장고:저장된 내용 활용하기
    7. 장고:변수 내보내기
    8. 장고:글쓰기
    9. 장고:페이징(페이지나누기)
    10. 장고:답변쓰기(댓글쓰기)
    11. 장고:추천,즐겨찾기
    12. 장고:새글(최신글) 나타내기
    13. 장고:썸머노트 설치
    14. 장고:네비게이션 바 만들기
    15. 장고:검색기능
    16. 장고:카테고리 만들기
    17. 장고:사진 올리기
    18. 장고:파일 업로드
    19. 장고:이메일app 만들기
    20. 장고:매직 그리드
  6. 장고:웹서비스
    1. 장고:Git
    2. 장고:리눅스에 올리기
    3. 장고:우분투에 올리기(nginx 사용)
    4. 장고:도커로 올리기
  7. 장고:팁

개요

검색기능은 DB에 쿼리하는 방식으로 이루어진다.

view 수정

목록을 조회하는 view를 수정한다.

다음과 같은 형태로 추가.

from django.db.models import Q  # 검색을 위함. filter에서 OR조건으로 조회하기 위한 함수.(장고제공)

def list(request):
    question_list = Question.objects.order_by('-create_date')  # 일단 객체 목록을 받아온다.
    keyword = request.GET.get('keyword', '')  # 검색어.  ''는 왜 필요할까? 없어도 되나?
    if keyword:  # 검색어가 있다면
        result = []  # 검색결과를 담기 위한 리스트를 만든다.
        keywords = keyword.split(' ')  # 공백이 있는 경우 나눈다.
        for kw in keywords:  # 띄어쓰기로 검색을 하는 경우가 많으니까, 다 찾아줘야지.
            result += question_list.filter(  # 검색해서 검색결과에 더한다.
            Q(subject__icontains=kw) |  # 제목검색
            Q(content__icontains=kw) |  # 내용검색
            Q(author__username__icontains=kw) |  # # question모델의 상위인 user모델의 username에서 검색.
            Q(answer__author__username__icontains=kw)  # 하위모델인 answer모델의 참조인 user모델의 username에서 검색.
            ).distinct()  # 중복된 내용이 있으면 제거하는 함수.
        question_list = result  # 모은 결과를 리스트에 담는다.
        
    .
    .
    .
    context = {  # keyword를 추가하여 반환해주자. 검색창에 검색어가 담겨 있게끔.
           'keyword': keyword,  # 검색어는 다시 돌려준다.
  • POST방식이 아니라 GET으로 받아오는 것은 뒤로가기 버튼을 누를 때 '만료된 페이지입니다'라는 문구가 뜨기 때문이다. 그럼 다시 찾아들어가야 하고.. 불편해.
  • ('만료된 페이지입니다' 문구는 POST요청 시 중복요청을 방지하기 위해 발생시키는 오류이다.)
  • subject__contains 대신 subject__icontains 형태를 사용하는 건 i를 붙였을 때 대소문자 구분없이 찾아주기 때문이다.

탬플릿 수정

검색창을 넣어야 하는 목록 탬플릿에 다음과 같이 추가한다.

<form id="searchForm" method="get" action="{% url 'pool:list' %}">
    <div class="input-group mb-3">
        <input type="text" class="form-control" name="keyword" placeholder="여따 검색하쇼" value="{{ keyword|default_if_none:'' }}">
        <div class="input-group-append">
        <input class="btn btn-outline-secondary" type="submit" id="btn_search" value="검색"></input>
    </form>
    </div>
</div>

정렬기능

검색 뿐 아니라 날짜 순, 댓글 순, 추천 순 등으로 정렬해야 할 때가 있다.

탬플릿 수정

form을 이용해 정렬기준을 전달한다.

검색 버튼을 누를 때 함께 전달되게 하기 위해 검색창을 정의하는 div 안에 다음과 같은 형태로 넣어준다.

        <div class="col-2">
        <select class="form-control so" name="ordering">
        <option value="recent" {% if so == 'recent' %}selected{% endif %}>최신순</option>
        <option value="recommend" {% if so == 'recommend' %}selected{% endif %}>추천순</option>
        <option value="popular" {% if so == 'popular' %}selected{% endif %}>인기순</option>
        </select>

뷰 수정

다음과 같은 형태의 내용을 추가한다.

from django.db.models import Count  # annotate에서 DB에 해당하는 무언가를 셀 때 사용하는 함수.

def list(request):
    .
    .
    .
    # 정렬 기능
    ordering = request.GET.get('ordering', 'recent')  # 정렬기준
    if ordering == 'recent':  # 시간순 정렬
        question_list = Question.objects.order_by('-create_date')
    elif ordering == 'popular':  # 댓글순 정렬
        question_list = Question.objects.annotate(num_answer=Count('answer')).order_by('-num_answer', '-create_date')
    elif ordering == 'recommend':  # 추천순 정렬
        question_list = Question.objects.annotate(num_voter=Count('voter')).order_by('-num_voter', '-create_date')
    else:  # recent
        pass
    .
    .
    .
    context = {  # ordering을 추가하여 반환해주자. 검색창에 검색어가 담겨 있게끔.
           'ordering': ordering,  # 선택한 정렬순서는 다시 돌려준다.