본문 바로가기
개발(Develop)/웹(Web) _프로젝트project

웹 / 책 리뷰 작성하고 저장하는 웹 만들기/ 책 리뷰 데이터베이스(DB)에 저장하고 가져와 사용하기/ Ajax, jQuery, HTML, 파이썬 Flask 프레임워크

by 왁왁s 2021. 6. 6.

이번 글에서는 책 리뷰를 작성하고 저장할 수 있는 웹 사이트를 만들어보겠다. 

 

파이참(Pycharm) 새 프로젝트 생성 후 개발환경 세팅하기

새 프로젝트를 생성해준다.

미리 바탕화면에서 project 폴더를 만들고, 그 안에 bookreview라는 폴더를 만든 뒤에

새 프로젝트를 만들 때 경로를 bookreview 폴더로 해주자.

 

그리고 아래에 새로운 환경에 venv가 입력 되어 있는 지 확인을 해주자. 

 

 

그리고 이전 글에서 했던 것처럼 세팅을 해줄 것이다.

이전 글 ▼

웹 / Flask 프레임워크를 활용한 서버 만들기 심화/ 로컬호스트로 서버 만들기

 

폴더를 2개 만드는데 이름은 static 폴더, templates 폴더이다.

 

static 폴더에는 CSS나 이미지 파일들을 담아둘 때 사용할 것이다.

그리고 templates 폴더에는 HTML 파일들을 담아둘 때 사용할 것이다.

 

그리고 서버로 활용할 app.py 파일을 생성해준다.

그리고 미리 templates 폴더에 index.html 파일을 생성해준다.

 


파이참(Pycharm) 라이브러리 설치하기

이번 프로젝트는 책 리뷰를 작성하는 웹 개발이다.

리뷰를 작성하고 저장하는 기능을 추가할 것이기 때문에 

데이터베이스가 사용이 된다.

 

그리고 자신의 컴퓨터를 서버로 돌려 웹을 열 것이기 때문에 관련 라이브러리인

'Flask'와 'pymongo'

를 파이참에서 다운로드 받아두자.

 

설치하는 방법을 모른다면 아래 클릭 ▼

파이참(PyCharm) 패키지 설치하기/  파이썬 라이브러리 설치/ pip 패키지 설치하기


자 그러면 이전에 다뤘던 서버부터 만들어보자.

app.py 파일에 아래 코드를 작성해준다.

 

이 전에 다뤘기 때문에 코드에 대한 설명은 넘어간다.

모른다면 아래 클릭 ▼

내 컴퓨터를 서버로 만들고 접속하기/ 웹서버 Flask 프레임워크로 구동하기/ 파이썬으로 웹 서버 만들기

app.py에 들어갈 서버, API 코드
from flask import Flask, render_template, jsonify, request
app = Flask(__name__)

from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client.dbhwan

## HTML을 주는 부분
@app.route('/')
def home():
    return render_template('index.html')

## API 역할을 하는 부분
@app.route('/review', methods=['POST'])
def write_review():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg': '이 요청은 POST!'})


@app.route('/review', methods=['GET'])
def read_reviews():
    sample_receive = request.args.get('sample_give')
    print(sample_receive)
    return jsonify({'msg': '이 요청은 GET!'})


if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)

오늘 할 프로젝트

우선 내 컴퓨터를 서버로 구동하고 localhost:5000으로

서버에 들어갔을 때 나타나는 화면은 아래와 같다.

 

해당 웹페이지가 리뷰 공간이라는 점과 사진이 나오고,

제목, 저자, 책 리뷰를 입력할 수 있는 공간'리뷰 작성 완료'라는 버튼이 나온다.

 

[리뷰 작성완료] 버튼을 눌렀을 때 아래에 등록이 된다.

 

그리고 등록된 리뷰는 '데이터베이스'에 저장된다.

이것을 한번 해보자 !



서버를 들어갔을 때 나타나는 기본 틀에 대한 코드는 제공하겠다.

아니라면 직접 만들어봐도 좋다. 그러나 이 글에서 중점을 둘 것은

 

클라이언트가 내가 만든 서버에 들어와

리뷰를 입력해서 완료 버튼을 눌렀을 때 리뷰 내용이

데이터베이스에 저장되는 것이 핵심인 점 알아두자.


'클라이언트가 입력한 값 데이터베이스에 넣기' (POST 방식)

 

생성한 index.html 파일에 들어갈 기본 틀 코드
<!DOCTYPE html>
<html lang="ko">

    <head>
        <!-- Webpage Title -->
        <title>HwanE의 책 리뷰공간</title>

        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
              integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
              crossorigin="anonymous">

        <!-- JS -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
                integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
                crossorigin="anonymous"></script>

        <!-- 구글폰트 -->
        <link href="https://fonts.googleapis.com/css?family=Do+Hyeon&display=swap" rel="stylesheet">

        <script type="text/javascript">

            $(document).ready(function () {
                $("#reviews-box").html("");
                showReview();
            });

            function makeReview() {
                $.ajax({
                    type: "POST",
                    url: "/review",
                    data: {sample_give:'샘플데이터'},
                    success: function (response) {
                        alert(response["msg"]);
                        window.location.reload();
                    }
                })
            }

            function showReview() {
                $.ajax({
                    type: "GET",
                    url: "/review?sample_give=샘플데이터",
                    data: {},
                    success: function (response) {
                        alert(response["msg"]);
                    }
                })
            }
        </script>

        <style type="text/css">
            * {
                font-family: "Do Hyeon", sans-serif;
            }

            h1,
            h5 {
                display: inline;
            }

            .info {
                margin-top: 20px;
                margin-bottom: 20px;
            }

            .review {
                text-align: center;
            }

            .reviews {
                margin-top: 100px;
            }
        </style>
    </head>

    <body>
        <div class="container">
            <img src="https://c.pxhere.com/photos/6c/37/photo-41952.jpg!d"
                 class="img-fluid" alt="Responsive image">
            <div class="info">
                <h1>여기는 HwanE의 리뷰 공간이에요.</h1>
                <p>재밌었던 책이나! 흥미진진했던 책의 리뷰를 남겨주세요. 다른 사람들에게도 추천하고 싶은 그런 책으로요 !</p>
                <div class="input-group mb-3">
                    <div class="input-group-prepend">
                        <span class="input-group-text">제목</span>
                    </div>
                    <input type="text" class="form-control" id="title">
                </div>
                <div class="input-group mb-3">
                    <div class="input-group-prepend">
                        <span class="input-group-text">저자</span>
                    </div>
                    <input type="text" class="form-control" id="author">
                </div>
                <div class="input-group mb-3">
                    <div class="input-group-prepend">
                        <span class="input-group-text">리뷰</span>
                    </div>
                    <textarea class="form-control" id="bookReview"
                              cols="30"
                              rows="5" placeholder="160자까지 입력할 수 있습니다."></textarea>
                </div>
                <div class="review">
                    <button onclick="makeReview()" type="button" class="btn btn-primary">리뷰 작성완료</button>
                </div>
            </div>
            <div class="reviews">
                <table class="table">
                    <thead>
                    <tr>
                        <th scope="col">제목</th>
                        <th scope="col">저자</th>
                        <th scope="col">리뷰</th>
                    </tr>
                    </thead>
                    <tbody id="reviews-box">
                    <tr>
                        <td>길동이의 개발일지</td>
                        <td>홍길동</td>
                        <td>완전 열심히 하시는 모습이 보기 좋네요.</td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </body>

</html>

우선 서버와 클라이언트 부분을 구분해서 코드를 작성해보자.

 

우선 서버 쪽 먼저 다뤄보자.

 

서버에서는 클라이언트가 입력한 리뷰의 내용을

받아와서 데이터베이스에 넣어주는 역할을 해야 한다.

app.py 파일/ 제목, 저자, 리뷰를 받아와 데이터베이스에 넣어주는 코드
## API 역할을 하는 부분
@app.route('/review', methods=['POST'])
def write_review():
    title_receive = request.form['title_give']
    author_receive = request.form['author_give']
    review_receive = request.form['review_give']
    put_db = {
        'title' : title_receive,
        'author' : author_receive,
        'review' : review_receive
    }
    db.bookreview.insert_one(put_db)
    return jsonify({'msg': '저장완료'})

그리고 클라이언트 쪽에서는

제목, 저자, 리뷰에 클라이언트가 입력한 내용을 서버로 보내주어야 한다.

 

어떻게 해야 할까?

제목과 저자, 리뷰를 입력하는 칸에 id 값을 가져와

제이쿼리로 작성하여 입력한 값을 가져와 서버로 보내주면 된다.

 



그럼 해당 요소들의 id 값을 찾아보자.

 

우선 제목 입력 칸의 id는 "title"

저자 입력 칸의 id는 "author"

리뷰 입력 칸의 id는 "bookReview"이다.

그리고 추가적으로 확인할 것은 버튼을 클릭(onClick) 했을 때

어떤 함수가 사용되는지를 확인한다.

 

자 그러면 버튼을 눌렀을 때 입력한 데이터가 서버로

전송이 되어야 하므로, 버튼 클릭했을 때 실행되는 함수인

makeReview( )에 서버로 보내는 코드를 작성해주면 된다.


function makeReview( ) 함수 부분을 아래와 같이 작성해준다.

입력 칸 요소들의 id'제이쿼리'를 사용하여 값을 가져온 후에

'Ajax' data : 부분에 실어서 서버로 보내주는 코드이다.

 

index.html 파일/ function makeReview( ) 부분 코드
           function makeReview() {
                let title = $('#title').val()
                let author = $('#author').val()
                let review = $('#bookReview').val()

                $.ajax({
                    type: "POST",
                    url: "/review",
                    data: {title_give:title,author_give:author, review_give:review},
                    success: function (response) {
                        alert(response["msg"]);
                        window.location.reload(); 
                    }
                })
            }

아래 코드에서 request.form[ ' ' ] 으로 title_give, author_give, review_give을 

받아왔기 때문에 Ajax 코드 부분과 이름을 일치시켜줘야 한다.

 

app.py 파일/ 제목, 저자, 리뷰를 받아와 데이터베이스에 넣어주는 코드
## API 역할을 하는 부분
@app.route('/review', methods=['POST'])
def write_review():
    title_receive = request.form['title_give']
    author_receive = request.form['author_give']
    review_receive = request.form['review_give']
    put_db = {
        'title' : title_receive,
        'author' : author_receive,
        'review' : review_receive
    }
    db.bookreview.insert_one(put_db)
    return jsonify({'msg': '저장완료'})

여기까지 했다면

우리는 사용자로부터 입력받은 데이터를 데이터베이스 저장할 수 있는 것이다!!!!

그럼 바로 정상 작동되는지 해보자.

localhost:5000으로 서버에 접속한다.


책 제목과 저자, 리뷰 내용을 입력해보자.

아무 내용이나 좋다.


그리고 [리뷰 작성완료]라는 버튼을 눌렀을 때

'저장완료'라는 Alert 가 나올 것이다. 

그러고는 데이터베이스에 입력한 내용이 저장이 되었다.

데이터베이스에 저장된 것을 확인하기 위해서는

Robo 3T를 열어서 확인해야 한다.

 

Robo3T 관련 내용은 아래에 ▼

Robo 3T 쉬운 설치/ MongoDB 편리하게 작업하는 Robo 3T/ Robo 3T 다운로드

 

Robo 3T를 확인했을 때 우리가 만든 DB 컬렉션인 'bookreview'에

우리가 입력한 내용이 정상적으로 들어간 것을 확인할 수 있다.

GOOD ~!



 

데이터베이스에 있는 값 가져와 나타내기 (GET 방식)

 

그렇다면 위에서 다룬 클라이언트로부터 입력받은 리뷰를 

데이터베이스에 넣었는데, 

 

데이터베이스에 넣은 모든 리뷰를 가져와 웹에 나타내는 작업을 해보자!


서버 쪽을 먼저 다뤄보자. 이번에는 클라이언트로부터 데이터를 받는 것이 아니라

데이터베이스를 조회해 데이터를 가져오기만 하면 된다.

그럼 아래와 같이 작성해주면 된다.

app.py 파일/ 서버에서 GET 방식 코드
@app.route('/review', methods=['GET'])
def read_reviews():
    client_reviews = list(db.bookreview.find({}, {'_id':False}))
    return jsonify({'all_reviews': client_reviews})

클라이언트로부터 입력받은 데이터를 'bookreview'라는 DB 컬렉션에 저장했기 때문에

bookreview 컬렉션에서 전부 find 해주면 되는 것이다.

{'_id : False'}는 긴 아이디 값을 가져오지 않는다는 것이고,

{ }는 모든 값을 가져온다는 것이다.

 

그리고 return 값으로 'all_reviews'라는 키(key) 값으로 DB로부터 find해서 가져온 데이터를 보낸다.


index.html 파일 / showReview( )함수 기본 틀
            function showReview() {
                $.ajax({
                    type: "GET",
                    url: "/review?sample_give=샘플데이터",
                    data: {},
                    success: function (response) {
                        alert(response["msg"]);
                    }
                })
            }

클라이언트 쪽을 다뤄보자. 우리가 수정해줄 부분은 여기인데,

위에서 다뤘던 makeReview( ) 함수는 버튼을 눌렀을 때 실행이 되는데,

showReview( ) 함수는 언제 실행되는지 확인을 해보자.


index.html 파일 / showReview 함수 실행되는 부분
            $(document).ready(function () {
                $("#reviews-box").html("");
                showReview();
            });

찾았다. showReview 함수는 $(document).ready ( function() {})에서 실행이 된다.

이는 이전에도 다뤘던 적이 있는데 

 

자세한 내용은 아래를 클릭하고  document를 검색해보자 ▼

Ajax와 jQuery/document 제이쿼리/ $(document).ready 함수

 

간단히 말하자면 웹이 로딩이 완료되면 실행하는 코드이다.

 

그렇다면 웹 브라우저를 새로고침하거나 처음 들어갔을 때

showReview( ); 함수가 실행이 된다.


그러면 showReview( ) 부분을 기본 틀에서 고쳐나가보자.

우선 클라이언트가 가져갈 데이터가 없으므로 

url: "/review?sample_give=샘플데이터"에서

물음표 뒤에 부분은 지워도 된다.

 


완성된 코드는 아래와 같다.

index.html 파일 / showReview( ) 완성된 코드
            function showReview() {
                $.ajax({
                    type: "GET",
                    url: "/review",
                    data: {},
                    success: function (response) {
                        let reviews = response["all_reviews"]
                        for(let i=0; i < reviews.length; i++){
                            let title = reviews[i]["title"]
                            let author = reviews[i]["author"]
                            let review = reviews[i]["review"]

                            let temp_html =
                            `<tr>
                                <td>${title}</td>
                                <td>${author}</td>
                                <td>${review}</td>
                              </tr>`

                         $("#reviews-box").append(temp_html)
                        }
                    }
                })
            }

우선 서버로부터 받아온 response에서 우리가 아까 return 값으로 넘긴

return jsonify({'all_reviews': client_reviews})

'all_reviews'를 찾아준다.

 

그리고 for문을 돌려 필요한 데이터인 title, author, review를 다른 변수에 담는다.

제목, 저자, 리뷰를 클라이언트에게 보여주기 위해 [표] 형태로 웹 하단에 추가해준다.

여기서 html 코드를 추가하기 위해 ` ` (백틱)을 사용하고 제이쿼리에 .append( ) 함수를 사용한다.

 

` `(백틱)과 .append 함수에 대한 자세한 내용은 아래를 참고 ▼

제이쿼리(jQuery)란 무엇인가/백틱과 .append 함수 사용법/.append 함수로 요소 추가하기

 


자 그러면 다시 크롬으로 localhost:5000을 접속해 우리가

입력했던 값들이 표 형태로 잘 나타내어졌는지 확인해보자.

홈페이지 하단에 제목, 저자, 리뷰가 '표' 형태로 나타나 있는 것을 확인할 수 있다.

그리고 Robo 3T를 통해 DB를 확인해보면 DB에도 데이터가 잘 저장되어 있는 것을 볼 수 있다.



그리고 클라이언트가 이렇게 제목, 저자, 리뷰에 대해 작성하고

[리뷰 작성완료] 버튼을 누르게 되면 어떻게 되는지 확인해보자.

 


'리뷰 작성완료' 버튼을 누르면 저장완료 알림 창이 뜨게 된다.


그리고 하단에는 클라이언트가 작성한 내용이 

아래로 추가된 것을 볼 수 있다.


Robo 3T를 통해 mongoDB 데이터베이스를 확인해보면

DB에도 클라이언트가 입력한 값이 잘 들어가 있는 것을 확인할 수 있다.

 

댓글