본문 바로가기
스파르타/Web

[Web] 화성땅 구매 - ( week 4 )

by bakcoding_sparta 2023. 4. 25.

브라우저에서 액션을 통해 서버의 API를 호출해서 DB에 값을 넣는 페이지를 만들어본다.

 

우선 프로젝트 세팅과 필요한 패키지들을 준비한다.

venv 설정을 하고

 

pip install flask

pip install pymongo

pip install dnspython

 

app.py

서버의 뼈대부터 만든다.

from flask import Flask, render_template, request, jsonify
app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route("/mars", methods=["POST"])
def mars_post():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg':'POST 연결 완료!'})

@app.route("/mars", methods=["GET"])
def mars_get():
    return jsonify({'msg':'GET 연결 완료!'})

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

 

index.html

브라우저의 뼈대를 만든다.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

        integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
        integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
        crossorigin="anonymous"></script>


    <title>선착순 공동구매</title>

    <style>
        * {
            font-family: "Gowun Batang", serif;
            color: white;
        }

        body {
            background-image: linear-gradient(0deg,
                    rgba(0, 0, 0, 0.5),
                    rgba(0, 0, 0, 0.5)),
            background-position: center;
            background-size: cover;
        }

        h1 {
            font-weight: bold;
        }

        .order {
            width: 500px;
            margin: 60px auto 0px auto;
            padding-bottom: 60px;
        }

        .mybtn {
            width: 100%;
        }

        .order>table {
            margin: 40px 0;
            font-size: 18px;
        }

        option {
            color: black;
        }
    </style>
    <script>
        $(document).ready(function () {
            show_order();
        });
        function show_order() {
            fetch('/mars').then((res) => res.json()).then((data) => {
                console.log(data)
                alert(data['msg'])
            })
        }
        function save_order() {
            let formData = new FormData();
            formData.append("sample_give", "샘플데이터");

            fetch('/mars', { method: "POST", body: formData }).then((res) => res.json()).then((data) => {
                console.log(data);
                alert(data["msg"]);
            });
        }
    </script>
</head>

<body>
    <div class="mask"></div>
    <div class="order">
        <h1>화성에 땅 사놓기!</h1>
        <h3>가격: 평 당 500원</h3>
        <p>
            화성에 땅을 사둘 수 있다고?<br />
            앞으로 백년 간 오지 않을 기회. 화성에서 즐기는 노후!
        </p>
        <div class="order-info">
            <div class="input-group mb-3">
                <span class="input-group-text">이름</span>
                <input id="name" type="text" class="form-control" />
            </div>
            <div class="input-group mb-3">
                <span class="input-group-text">주소</span>
                <input id="address" type="text" class="form-control" />
            </div>
            <div class="input-group mb-3">
                <label class="input-group-text" for="size">평수</label>
                <select class="form-select" id="size">
                    <option selected>-- 주문 평수 --</option>
                    <option value="10평">10평</option>
                    <option value="20평">20평</option>
                    <option value="30평">30평</option>
                    <option value="40평">40평</option>
                    <option value="50평">50평</option>
                </select>
            </div>
            <button onclick="save_order()" type="button" class="btn btn-warning mybtn">
                주문하기
            </button>
        </div>
        <table class="table">
            <thead>
                <tr>
                    <th scope="col">이름</th>
                    <th scope="col">주소</th>
                    <th scope="col">평수</th>
                </tr>
            </thead>
            <tbody id="order-box">
                <tr>
                    <td>홍길동</td>
                    <td>서울시 용산구</td>
                    <td>20평</td>
                </tr>
                <tr>
                    <td>임꺽정</td>
                    <td>부산시 동구</td>
                    <td>10평</td>
                </tr>
                <tr>
                    <td>세종대왕</td>
                    <td>세종시 대왕구</td>
                    <td>30평</td>
                </tr>
            </tbody>
        </table>
    </div>
</body>

</html>

 

현재 브라우저의 상태를 확인해 본다.

 

뼈대는 완성되었고 브라우저에서 동작을 받아서 DB에 데이터를 저장하고 가져오는 기능을 구현해야 한다.

 

저장하기

데이터 명세

저장할 정보는 이름, 주소, 평수이며 주문하기 버튼을 눌렀을 때 서버를 통해서 DB에 저장되어야 한다.

 

클라이언트와 서버 연결확인

클라이언트에서 버튼을 클릭했을 때 서버와 통신을 하기 때문에 여기서 테스트 동작을 구현하고 호출이 잘되는지 확인해 본다.

주문하기를 눌렀을 때 서버에 구현한 대로 값이 들어오는 것을 확인할 수 있다.

 

구현

저장하기

서버의 저장기능부터 구현해 본다.

서버가 할 일은 이름, 주소, 평수 값을 받아서 DB로 보내주면 된다.

 

패키지를 임포트 한다.

from pymongo import MongoClient
client = MongoClient('mongodb+srv://sparta:test@sparta.lls2xk0.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta

그리고 브라우저에서 들어오는 데이터를 정리해서 딕셔너리로 만들고 서버로 전송한다.

@app.route("/mars", methods=["POST"])
def mars_post():
    # sample_receive = request.form['sample_give']
    # print(sample_receive)
    name_receive = request.form['name_give']
    address_receive = request.form['address_give']
    size_receive = request.form['size_give']
   
    doc = {
        'name' : name_receive,
        'address' : address_receive,
        'size' : size_receive
    }
    db.mars.insert_one(doc)

    # return jsonify({'msg':'POST 연결 완료!'})
    return jsonify({'msg':'저장완료!'})

 

클라이언트에서는 저장할 때 호출되는 함수에서 서버의 저장하는 API를 호출해야 한다.

function save_order() {
            let name = $('#name').val()
            let address = $('#address').val()
            let size = $('#size').val()

            let formData = new FormData();
            // formData.append("sample_give", "샘플데이터");
            formData.append("name_give", name);
            formData.append("address_give", address);
            formData.append("size_give", size);


            fetch('/mars', { method: "POST", body: formData }).then((res) => res.json()).then((data) => {
                // console.log(data);
                alert(data["msg"]);
            });
        }

html의 id값을 통해서 값을 가져온다. 가져온 값의 정보는 formData로 묶어서 서버로 Post 방식으로 전송한다.

 

브라우저에서 기능을 테스트한다.

동작은 문제없이 진행되었고 실제 값이 저장되어 있는지 DB를 확인해 본다.

성공적으로 API호출을 통해서 값이 저장되었다.

 

추가적인 기능으로 주문하기가 진행되고 나서 페이지를 새로고침 하도록 한다.

fetch('/mars', { method: "POST", body: formData }).then((res) => res.json()).then((data) => {
                // console.log(data);
                alert(data["msg"]);
                window.location.reload()
            });

window.location.reload() 함수를 실행시키면 페이지가 새로고침된다.

 

불러오기

값을 불러오는 시점은 페이지가 로딩될 때 되어야 한다.

우선 서버에서 DB의 값을 가져오는 코드를 구현한다.

@app.route("/mars", methods=["GET"])
def mars_get():
    mars_data = list(db.mars.find({},{'_id':False}))

    # return jsonify({'msg':'GET 연결 완료!'})
    return jsonify({'result':mars_data})

 

해당 API가 호출될 때 반환값으로 필요한 정보를 보낸다.

 

클라이언트에서 페이지가 로드되는 시점에 호출되는 함수는 다음이다.

function show_order() {
            fetch('/mars').then((res) => res.json()).then((data) => {
                console.log(data)
                // alert(data['msg'])
            })
        }

우선 값이 제대로 들어오는지부터 확인한다.

 

페이지를 새로고침 하면 다시 로드되면서 API가 호출되고 값을 가져오는 것을 볼 수 있다.

이제 가져온 값을 가지고 html을 만들어준다.

 

function show_order() {
            fetch('/mars').then((res) => res.json()).then((data) => {
                console.log(data)
                // alert(data['msg'])
                let rows = data['result']
                $('#order-box').empty()
                rows.forEach((a)=>{
                    // console.log(a)
                    let name = a['name']
                    let address = a['address']
                    let size = a['size']
                    let temp_html = `<tr>
                                        <td>${name}</td>
                                        <td>${address}</td>
                                        <td>${size}</td>
                                    </tr>`
                    $('#order-box').append(temp_html)
                })
            })
        }

 

테스트를 위해서 값을 추가로 넣어주고 DB에 저장된 값을 확인한다.

그리고 현재 페이지를 확인한다.

서버의 값을 잘 가져와서 html을 그려주고 있다.