[Python #19] [Django #12] 검색 기능 UI 다듬기

in SCT.암호화폐.Cryptolast month (edited)

pixabay


검색 기능 UI를 좀 더 다듬어 본다. HTML form을 그대로 사용했고 CSS 가 없다 보니 영 보기 안 좋다.

구상

  1. 큰 검색 박스 하나를 메인에 두고, 구현된 세 개 기능(태그 검색, 타이틀 검색, 내용 검색) 중 내용 검색만 노출
  2. 복수 키워드를 받을 수 있어야 하므로, 여러 개를 받을 수 있는 기능 구현
  3. [상세 검색] 버튼 하나 추가, 클릭 시 태그 검색, 타이틀 검색, 내용 검색 세 가지 노출

더 상세하게 만들고 싶지만 시간이 많이 들 것 같아 일단 이 정도로 구현한다. 게다가 CSS, JS는 초짜라 어떻게 내 힘으로 할 수가 없어 더 많은 기능은 욕심이다. 이 정도도 오픈소스의 힘을 빌려 본다.

소스 탐색1

인터넷에서 검색 박스 마크업을 검색해 보니 역시 Bootstrap 예제가 많이 나온다.
https://colorlib.com/wp/free-css3-html5-search-form-examples/ 에서 가장 마음에 드는 v4를 사용하자. 복수 키워드 검색까지 구현돼 있어 1, 2번은 한 번에 해결될 것 같다. (#다운로드고고#오픈소스감사)

소스 탐색2

3번은 w3schools에 예제가 있다. 필요한 코드만 가져가면 될 거 같다.
https://www.w3schools.com/howto/howto_js_collapsible.asp

그런데 한 가지 문제가 있다. 이 두 개 코드를 합치는 방법을 잘 모르겠다. 메인 검색 박스 우측에 작은 버튼 하나 만들고, 누르면 아래로 상세 메뉴가 노출되게 하는 게 목적인데... ㅎㅎㅎ 그건 차차 배우면서 하고 일단 순서대로 노출 시켜본다. 배경색 정도는 직접 추가하자. 내가 좋아하는 파랑, 초록, 노랑, 빨강 단색으로...

구현

우선 프로젝트 root에 static 폴더 하나를 만들고 하위에 css, images, js 폴더를 만들어 위에서 다운로드 한 파일을 각각 위치에 맞게 넣는다.

다음은 장고에서 지원하는 방법으로 static 폴더를 읽어오도록 settings.py에서 static 파일 경로를 지정해 준다.

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

검색 기능은 메인에 노출해야 하므로 base.html에 코드를 추가하자. 주의할 점은 {% load static %}로 static 파일을 읽어야 한다. 또한 <link href="{% static 'css/main.css' %}" rel="stylesheet" />로 css 파일을 읽어온다.

{% load static %}
{% load post_extras %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Poppins:400,800" rel="stylesheet" />
<link href="{% static 'css/main.css' %}" rel="stylesheet" />

{% spaceless %}
{% endspaceless %}

<html lang="en">
  <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <title>D_Blog</title>
      
  </head>
  <body>
      <header>
          <nav>
              <div class="s004">
              <form action="/{{ request.path | get_account_form_url }}/search/" method="get">
                  <div class="inner-form">
                    <div class="input-field">
                      <input class="form-control" id="choices-text-preset-values" name="texts" type="text" placeholder="Type to search..." />
                        <button class="btn-search" type="submit">
                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                          <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
                            </svg>
                        </button>
                      </div>
                  </div>
              </form>
              </div>
              <div class="collapsible-container">
                  <button class="collapsible">Advanced search</button>
                  <div class="content">
                      <form class="adv-form" action="/{{ request.path | get_account_form_url }}/search/" method="get">
                          <input id="tags" type="text" name="tags" value="" placeholder="tags">
                          <input id="titles" type="text" name="titles" value="" placeholder="titles">
                          <input id="texts" type="text" name="texts" value="" placeholder="texts">
                          <input type="submit" value="Search">
                      </form>
                  </div>
              </div>
          </nav>
      </header>

      <script src="{% static 'js/choices.js' %}"></script>
      <script>
          var textPresetVal = new Choices('#choices-text-preset-values', {
              removeItemButton: true,
          });
          
          var coll = document.getElementsByClassName("collapsible");
          var i;
          for (i = 0; i < coll.length; i++) {
              coll[i].addEventListener("click", function() {
                  this.classList.toggle("active");
                  var content = this.nextElementSibling;
                  if (content.style.maxHeight){
                      content.style.maxHeight = null;
                  } else {
                      content.style.maxHeight = content.scrollHeight + "px";
                  }
              });
          }
      </script>
{% block content %}
{% endblock content %}
    </body>
</html>

main.css의 내용은 첨부하지 않는다. 양이 너무 많고, 어차피 위 두 링크에서 확인 가능하다.

결과

검색어 복수 입력한 상태 & 상세 검색 접힌 상태

상세 검색 펼친 상태

색상이 너무 강렬하다. 이건 차차 손 봐야겠다.


[Cookie 😅]
Python 3.7.4
Django 2.2.4
steem-python 1.0.1
goorm IDE 1.3

Sort:  

[US$18.50](▼39%)[Xiaomi]🚨2020 최신 항바이러스 필터 입고!!🚨 샤오미 공기청정기 필터 / 미에어 필터 / 고효율 정화 / 활성탄 필터 / 포름알데히드 제거 / 고밀도 헤파필터 / 무료배송

WWW.QOO10.COM

@june0620 transfered 1.0 KRWP to @krwp.burn. voting percent : 0.70%, voting power : 76.71%, steem power : 1912028.04, STU KRW : 1200.
@june0620 staking status : 50 KRWP
@june0620 limit for KRWP voting service : 0.1 KRWP (rate : 0.002)
What you sent : 1.0 KRWP
Refund balance : 0.9 KRWP [46862312 - 6f64ab83ad092df5b9e6f8f1b9349d4d4b3f6cb6]

Coin Marketplace

STEEM 0.15
TRX 0.03
JST 0.026
BTC 12189.42
ETH 379.00
USDT 1.00
SBD 0.99