강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

양성현님의 프로필 이미지
양성현

작성한 질문수

남박사의 파이썬으로 실전 웹사이트 만들기

게시판만들기 - 글 리스트

검색기능 질문

해결된 질문

작성

·

11

0

from flask import Flask
from flask import request
from flask import render_template
from flask_pymongo import PyMongo
from datetime import datetime
from bson.objectid import ObjectId
from flask import abort
from flask import redirect
from flask import url_for
import time
import math

app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://localhost:27017/myweb"
mongo = PyMongo(app)

@app.template_filter("formatdatetime")
def format_datetime(value):
    if value is None:
        return ""
    

    
    now_timestamp = time.time()
    offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
    value = datetime.fromtimestamp((int(value) / 1000)) + offset
    return value.strftime('%Y-%m-%d %H:%M:%S')
@app.route("/list")
def lists():
    #페이지 값(값이 없는 경우 기본값은 1)
    page = request.args.get("page", 1, type=int)
    #한페이지당 몇개의 게시물을 출력할지
    limit = request.args.get("limit", 7, type = int)

    search = request.args.get("search", -1, type=int)
    keyword = request.args.get("keyword", type=str)

    #최종적으로 완성된 쿼리를 만들 변수
    query = {}
    #검색어 상태를 추가할 리스트 변수
    search_list = []

    if search == 0:
        search_list.append({"title":{"$regex": keyword}})
    elif search ==1:
        search_list.append({"contents":{"$regex": keyword}})
    elif search ==2:
        search_list.append({"title":{"$regex": keyword}})
        search_list.append({"contents":{"$regex": keyword}})
    elif search == 3:
        search_list.append({"name":{"$regex": keyword}})

    #검색 대상이 한개라도 존재할 경우 query 변수에 $or 리스트를 쿼리 합니다.
    if len(search_list) > 0:
        query = {"$or": search_list}
    
    print(query)


    board = mongo.db.board
    datas = board.find(query).skip((page - 1)*limit).limit(limit)

    #게시물의 총 갯수
    tot_count = board.find(query).count()
    #마지막 페이지의 수를 구합니다.
    last_page_num = math.ceil(tot_count / limit)

    #페이지 블럭을 5개씩 표기
    block_size = 5
    #현재 블럭의 위치
    block_num=int((page-1)/ block_size)
    #블럭의 시작 위치
    block_start = int((block_size * block_num) +1)
    #블럭의 끝 위치
    block_last = math.ceil(block_start +(block_size - 1))
    return render_template(
                           "list.html",
                           datas = datas, 
                           limit=limit, 
                           page=page, 
                           block_start=block_start, 
                           block_last=block_last, 
                           last_page_num=last_page_num,
                           search=search,
                           keyword=keyword)

@app.route("/view/<idx>")
def board_view(idx):
    # idx = request.args.get("idx")
    if idx is not None:
        board = mongo.db.board
        data = board.find_one({"_id": ObjectId(idx)})

        if data is not None:
            result = {
                "id" : data.get("_id"),
                "name" : data.get("name"),
                "title" : data.get("title"),
                "contents" : data.get("contents"),
                "pubdate" : data.get("pubdate"),
                "view" : data.get("view"),
            }

            return render_template("view.html", result=result)
    return abort(400)


@app.route("/wirte", methods = ["GET", "POST"])
def board_wirte():
    if request.method == "POST":
        name = request.form.get("name")
        title = request.form.get("title")
        contents = request.form.get("contents")
        print(name, title, contents)

        current_utc_time = round(datetime.utcnow().timestamp() * 1000)
        board = mongo.db.board
        post = {
            "name" : name,
            "title" : title,
            "contents" : contents,
            "pubdate" : current_utc_time,
            "view" : 0,
        }

        x = board.insert_one(post)
        print(x.inserted_id)
        return redirect(url_for("board_view", idx=x.inserted_id))
    else:
        return render_template("wirte.html")



if __name__ == "__main__":
    app.run(debug = True)









<script>
    function search() {
       var v_search = document.getElementById("search").value;
       var v_keyword = document.getElementById("keyword").value;

       if(v_search == "" || v_keyword == ""){
            return false;
       } else{
            self.location.href="{{url_for('lists')}}?search=" + v_search + "&keyword=" + v_keyword;
       }
    }
</script>

{% if datas.count() > 0%}
<table>
    <thead>
        <tr>
            <td>번호</td>
            <td>제목</td>
            <td>이름</td>
            <td>날짜</td>
            <td>조회수</td>
        </tr>
    </thead>
    <tbody>
        <!--반복되는 구간-->
        {%for data in datas%}
        <tr>
            <td>{{loop.index + (page - 1) * limit}}</td>
            <td><a href="{{url_for('board_view', idx=data._id, page=page, search=search, keyword=keyword)}}">{{data.title}}</a></td>
            <td>{{data.name}}</td>
            <td>{{data.pubdate | formatdatetime}}</td>
            <td>{{data.view}}</td>
        </tr>
        <!--반복되는 구간 끝-->
        {%endfor%}
    </tbody>
</table>
{%if block_start -1 > 0%}
    <a href="{{url_for('lists', page=block_start - 1, search=search, keyword=keyword)}}">[이전]</a>
{%endif%}

{%for i in range(block_start, block_last + 1)%}
    {% if i > last_page_num%}
    {%else%}
        {%if i == page%}
        <b>{{i}}</b>
    {%else%}
        <a href="{{url_for('lists', page=i, search=search, keyword=keyword)}}">{{i}}</a>
        {%endif%}
    {%endif%}
{%endfor%}

{%if block_last < last_page_num%}
    <a href="{{url_for('lists', page=block_last+ 1, search=search, keyword=keyword)}}">[다음]</a>
{%endif%}

<select name="search" id="search">
    <option value="">검색대상</option>
    <option value="0">제목</option>
    <option value="1">내용</option>
    <option value="2">제목 + 내용</option>
    <option value="3">작성자</option>
</select>
<input type="text" name="keyword" id="keyword">
<input type="button" value="검색" onclick="search()">
{% else %}
<h3>데이터가 없습니다.</h3>
{%endif%}

 

분명 똑같이 했는데 왜 검색이 안되고 무반응인지 잘 모르겠어요. 뭐가 문제일까요?

답변 2

0

남박사님의 프로필 이미지
남박사
지식공유자

일단 그런 경우에는 디버깅을 할 수 있는 코드를 좀 추가하여 어느 구간에서 문제가 발생하는지를 찾아보는게 좋습니다. 일단 검색 버튼을 누르면 search() 함수가 실행되는데 함수 내에서 v_search 값과 v_keyword 값을 alert() 함수를 사용해서 먼저 확인 해보고, 또한 url_for('list') 가 제대로 값을 갖고 있는지 그래서 해당 self.location.href 에 제대로 된 값이 전달 되는지 부터 확인해보는게 좋을듯 합니다.

그값에 문제가 없다고 판단되면, 그러니까 프론트 영역은 문제가 없다면 이제는 /list 라우트에 선언된 코드들을 확인해볼 차례입니다. 넘어온 값들을 모두 print() 함수를 사용해서 화면에 출력해보면서 값을 확인하고 코드 구간마다 print() 를 사용해 어떤 구간까지 실행되는지도 확인 해볼 수 있습니다.

그런식으로 디버깅을 해보면서 원인을 찾아보시는걸 추천드리며 또 궁금한 사항이 생기면 질문 주시기 바랍니다.

0

안녕하세요, 인프런 AI 인턴입니다. 양성현님이 작성해주신 코드를 보고 몇 가지 확인할 사항이 있어서 안내드립니다.

검색 기능이 예상대로 작동하지 않는 경우는 여러 가지 원인이 있을 수 있습니다. 아래 몇 가지 점을 확인해 주세요:

  1. HTML에서의 JavaScript 부분: 검색 버튼을 클릭했을 때 JavaScript의 search() 함수가 제대로 작동하는지 확인하세요. 검색 필드의 값이 제대로 전달되는지 console.log()로 출력해 보시면 도움이 될 것입니다.

  2. Regex 사용: MongoDB의 $regex 연산자를 사용할 때, 정규 표현식 패턴이 정확한지 확인해 주세요. 예를 들어, 사용자가 입력한 키워드 주변에 불필요한 공백이 있을 수 있습니다. 이 경우 검색이 되지 않을 수 있습니다.

   search_list.append({"title": {"$regex": keyword, "$options": "i"}})

$options: "i"를 추가하면 대소문자를 구분하지 않고 검색할 수 있습니다.

  1. 데이터베이스 연결 및 쿼리: 데이터베이스가 제대로 연결되어 있고 올바른 컬렉션에서 데이터를 검색하고 있는지 확인해 주세요.

  2. 쿼리 출력 확인: print(query)로 출력되는 쿼리를 실제로 MongoDB에서 실행해 봐서 결과가 나오는지 확인해 보세요. 쿼리가 올바르게 작성되었는지 검토하는 것이 중요합니다.

  3. 라우트 경로 오타: 코드 내에서 /write 라우트 오타가 있습니다.

   @app.route("/wirte", methods=["GET", "POST"])
   def board_wirte():

위 부분을 /writeboard_write로 수정해야 합니다.

  1. 템플릿 파일 경로 및 위치: 템플릿 파일의 경로가 올바른지, Flask가 올바른 템플릿 폴더를 참조하고 있는지도 확인해 주세요.

관련하여 비슷한 문제를 다룬 질문이 있습니다. 게시판 검색기능 구현 후 데이터를 검색하여도 데이터 없음으로 나옵니다.를 참고해 보실 수 있습니다. 이 질문에서는 $regex 사용이나 query의 세밀한 조건 설정 등에서 실수할 수 있는 부분이 언급되었습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

양성현님의 프로필 이미지
양성현

작성한 질문수

질문하기