2019.05.13 장고 페이지 서칭 기능 구현하기

서칭 기능 구현하기

  1. 데이터베이스에 질의문 (query 문)/ 애초에 해당애들만 뽑아오기
    1. documents = Document.objects.filter(title__contains = "1")
    2. documents = get_list_or_404(Document, title__contains = "1")
  2. 코드레벨 검색 (DB에서 다 가지고 온 다음에 뽑아내기 )
    1. 파이썬 코드레벨에서 검색
    2. 다 가지고 온 다음에 for문 같은 것을 돌려야 한다.
  3. DB에서 가지고 오는게 제일 빠른데 항상 병목 현상은 db에서 발생한다.
    1. 서비스가 느려지고 그럴 수 있다.
    2. 데이터베이스의 쿼리질의문을 줄인다.?
      1. 하나씩 물어보는 방법과 한번에 물어보는 방법이 있다.
      2. 하지만 그렇게 하면 질의문이 길어져서 해석하는데 시간이 오래 걸릴 수 있다.

로직 생각

  1. 검색어가 들어온다.
  2. 검색어를 받아서 제대로 받았는지 확인한다.
  3. filter 메소드를 사용한다.
    1. 어떤 항목을 검색할 것이냐?
      1. 내용/ 작성자 등
    2. 어떤 옵션으로 검색할 것이냐?
      1. 특정단어가 들어가있는지/ 처음에 시작하는지/ 대문자 / 소문자 등등

쉘에서 filter 연습하기

  1. objects는 manage이다. 모델명.objects. 인 경우
  2. filter( a, b) : a이고 b 인것
  3. filter(filed이름) = 매칭
  4. filter(필드이름__옵션)
  5. filter(title__startswitch = "") : 제목이 특정 문구로 시작하는 것
    1. (title__istartswitch) : 제목이 대소문자 구분 없이 특정 문구로 시작
    2. "" % : 뒤에 특정 애들이 붙을 수 있다.
  6. filter(title__endswitch = "") : 특정 문구로 끝나는지
  7. filter(title__iexact=="" ) : 대소문자 구분없이 특정 제목이 있나?
  8. filter(title__icontains = "") : 대소문자 구분없이 중간에 포함하고 있나?
  9. 우리가 이렇게 매칭한 것은 로컬필드가 검색이 가능하다.
    1. 기본 필드들이 로컬 필드 이다.
    2. 그럼 연결된 foreign key혹은 primary key는 어떻게 해야하나?
  10. filter(category__name="c1") : 카테고리 필드의 이름이 c1인 것
  11. filter(category__ name__endswith =" ") : 카테고리의 이름이 "" 으로 끝나는 애들
    1. %endswith : 앞에 특정 애들이 붙을 수 있다.
  12. 여러개 모델에서 찾는 것도 추가적으로 구현할 수 있다.
    1. by 일래스틱서치 - 우리의 스팩이 한줄 더 늘 수 있다.
    2. 한글 검색이 특히

정리(위의 예시를 바탕으로 정리한 것입니다)

  1. 필드명 = "값" 매칭
  2. 필드명__exact = "값" 매칭
  3. 필드명__iexact = "값" 대소문자 구분 없이 매칭
  4. 필드명__ startswich,필드명 __istartswich : "값"으로 시작
  5. 필드명__ endswitch, 필드명__iendswitch : "값"으로 끝
  6. 필드명__ contains , 필드명__icontains : "값"을 포함하느냐?
  7. Foreignkey 매칭
    1. 필드명__해당모델의 필드명 : 매칭
    2. 필드명__ 해당모델의 필드명__ 옵션 : 해당 모델의 필드명이 해당 옵션으로 매칭
  8. 필드명__ gt=값, 필드명__gte= 값 크다, 크거나 같다.
    1. ex) created__gt = 오늘 : 작성일이 오늘보다 크다. (오늘 00시 이후)
  9. 필드명__ lt =값 , 필드명__lte = 값 작다, 작거나 같다.
    1. ex) created__lt = 오늘 : 작성일이 오늘보다 이전이다. (datetime.now())
    2. ex) 판매시작일 __lt = 오늘 : 판매시작일 설정값이 오늘보다 작거나 같으면 판매시작

서칭 버튼 구현 (템플릿)

스크린샷 2019-05-14 오후 12 02 22

서칭 views.py 구현

26EFCA46-24B9-400F-BA1F-FA2653B79856
  • 서칭은 기본적으로 list를 띄어주는 상황에서 가능하다.
  • search_key가 없으면 그냥 get_list를 통해 모든 list를 가지고 온다.

서칭 심화 구현 - OR 구현하기

  • 특정 필드가 아닌 제목, 본문, 사용자이름과 관련해서 동시에 서칭하고 싶을 때!

Q 객체 사용하기

>>> from django.db.models import Q
>>> Q(title__icontains='1')
<Q: (AND: ('title__icontains', '1'))>
>>> default_q = Q(title__icontains='1')
>>> second_q = Q(text__icontains='1')
>>> default_q | second__q
<Q: (OR: ('title__icontains', '1'), ('text__icontains', '1'))>
>>> Document.objects.filter(default_q|second_q)

Q객체는 우리가 기존에 쓰던 필터를 그대로 쓰게 해주는데, 일반 필더안에서는 and만 가능해서 Q객체를 활용해서 or을 사용가능하게 된다.

  1. objects.filter() : filter 매서드에 들어가는 매개변수들은 항상 and 연산을 한다.
  2. or 연산을 하고 싶퍼서 Q객체를 사용한다.
  3. 사용법은 filter에 들어가는 매개변수의 작성법과 똑같다.
    1. Q() | Q() : OR
    2. Q() & Q() : AND
    3. ~Q() :NOT
    4. 구글 검색 연산자
      1. 작성자, 제목, 본문에 대해서 다 검색할 수 있도록
      2. 체크박스 보이기
      3. 체크박스 값확인
      4. Q객체를 어떻게 만들 것인가?

제목, 본문에서 해당 내용 같이 검색하도록 하기 (by Q객체 - views.py)

13E315E3-4C12-4F4F-85F3-D58C61BB2C93
  • title_q와 text_q를 변수로 받고 Q 객체를 활용하여 OR 필터가 가능하도록 한다.
  • 그 이외는 모두 한개의 필터를 사용할 때와 같다.

체크박스로 작성자/ 제목/ 내용 등을 구분할 때

views.py 구현하기

4C77E9AE-3BE4-4663-BBCD-309372DBBD94
  1. request.METHOD.get : 마지막 들어오는 1개만 표시
  2. request.METHOD.getlist : 리스트 형태로 모두 가지고 온다.
    1. search_type = request.GET.getlist('search_type',None)
  3. 기본적으로 search_type이 없으면 text에서 검색하도록 한다.
  4. 각각 title/ text/ username이 들어왔을 때에 따라서 분기하여 구현한다.

templates 구현하기

스크린샷 2019-05-14 오후 8 45 29
  • form을 get 방식으로 받아오고 3가지를 모두 search_type이라는 이름으로 받아온다.
  • 따라서 views.py에서 getlist를 통해 모두 가지고 와야 한다.

+ Recent posts