항해 99/사전 기본 스터디

파이썬(Python)으로 버킷 리스트 만들기 (완료/수정/삭제)

U_D 2022. 2. 25. 22:53
언어 : 파이썬(Python)
IDE : 파이참(PyCharm)
DB : mongoDB

 

기능 연습 _ 버킷리스트 입력 / 완료버튼 누르면 항목에 줄긋고 취소버튼 나오기 / 삭제 버튼 누르면 항목 삭제

 

 

1) 버킷리스트 기록 API (Create→ POST)

  • 요청 정보 : URL= /bucket, 요청 방식 = POST
  • 클라(ajax) → 서버(flask) : bucket
  • 서버(flask) → 클라(ajax) : 메시지를 보냄 (기록 완료!)
  • 단! 서버에서 한 가지 일을 더 해야한다. → 항목별로 번호를 만들어 함께 넣어주기

↓서버 만들기

@app.route("/bucket", methods=["POST"])
def bucket_post():
    bucket_receive = request.form['bucket_give']

    bucket_list = list(db.bucket.find({},{'_id':False}))
    count = len(bucket_list) + 1

    doc = {
        'num':count,
        'bucket':bucket_receive,
        'done':0
    }
    db.bucket.insert_one(doc)

    return jsonify({'msg': '등록 완료!'})

↓클라이언트 만들기

function save_bucket() {
    let bucket = $('#bucket').val()

    $.ajax({
        type: "POST",
        url: "/bucket",
        data: {bucket_give: bucket},
        success: function (response) {
            alert(response["msg"])
            window.location.reload()
        }
    });
}

 

2) 버킷리스트 조회 API (Read→ GET)

  • 요청 정보 : URL= /bucket, 요청 방식 = GET
  • 클라(ajax) → 서버(flask) : (없음)
  • 서버(flask) → 클라(ajax) : 전체 버킷리스트를 보여주기

↓서버 만들기

@app.route("/bucket", methods=["GET"])
def bucket_get():
    bucket_list = list(db.bucket.find({}, {'_id': False}))
    return jsonify({'buckets': bucket_list})

↓클라이언트 만들기

function show_bucket() {
    $.ajax({
        type: "GET",
        url: "/bucket",
        data: {},
        success: function (response) {
            let rows = response['buckets']
            for (let i = 0; i < rows.length; i++) {
                let bucket = rows[i]['bucket']
                let num = rows[i]['num']
                let done = rows[i]['done']

                let temp_html = ``

                if (done == 0) {
                    temp_html = `<li>
                        <h2>✅ ${bucket}</h2>
                        <button onclick="done_bucket(${num})" type="button" class="CheckBtn" >완료!
                        </button><button onclick="delete_bucket(${num})" class="delBtn">X</button>
                    </li>`
                } else {
                    temp_html = `<li>
                        <h2 class ="done">✅ ${bucket}</h2>
                        </button><button onclick="delete_bucket(${num})" class="delBtn">X</button>
                    </li>`
                }

                $('#bucket-list').append(temp_html)
            }
        }
    });
}

*삭제버튼을 버킷이 기입되면 함께 붙여지도록 만들어주었다.

 

 

3) 버킷리스트 완료 API (Update→ POST)

  • 요청 정보 : URL= /bucket/done, 요청 방식 = POST
  • 클라(ajax) → 서버(flask) : num (버킷 넘버)
  • 서버(flask) → 클라(ajax) : 메시지를 보냄 (버킷 완료!)

↓서버 만들기

@app.route("/bucket/done", methods=["POST"])
def bucket_done():
    num_receive = request.form['num_give']
    db.bucket.update_one({'num': int(num_receive)}, {'$set': {'done': 1}})
    return jsonify({'msg': '버킷 완료!'})

*int는 문자를 숫자로 바꿔주는 함수

 

↓클라이언트 만들기

function done_bucket(num) {
    $.ajax({
        type: "POST",
        url: "/bucket/done",
        data: {num_give: num},
        success: function (response) {
            alert(response["msg"])
        }
    });
}

 

 

↓완성본 

 

 

 

 

 

4) 버킷리스트 삭제 API (Delete→ Delete)

  • 요청 정보 : URL= /bucket, 요청 방식 = Delete
  • 클라(ajax) → 서버(flask) : num (버킷 넘버)
  • 서버(flask) → 클라(ajax) : 메시지를 보냄 (삭제 완료!)
문제의 삭제 버튼이었다... 당연히 삭제 기능이 있어야 된다는 생각에 예제에는 없지만 혼자 만들어보았다.
하지만 생각만큼 간단하게 돌아가지 않았다. 처음에는 HOST 요청 방법으로 시도 했으나 계속 되지 않았고
remove, delete 등 다양하게 도전했지만 말을 듣지 않았다.

그러던 와중에 파이썬 삭제 기능중에 method = delete 문구를 구글에서 보고 혹시나 하는 마음에
요청 방법을 바꿨더니 귀신처럼 되었다.

3시간 정도 지나고 완성되었을때 기분은 너무 좋았다 ㅠㅠ 정확한 코드인지는 모르겠지만
일단 시행은 되었기에 뿌듯하게 기록을 남겨본다!

 

↓서버 만들기

@app.route("/bucket", methods=["delete"])
def bucket_delete():
    num_receive = request.form['num_give']
    db.bucket.delete_one({'num': int(num_receive)})
    return jsonify({'msg': '삭제 완료!'})

 

↓클라이언트 만들기

function delete_bucket(num) {
    $.ajax({
        type: "delete",
        url: "/bucket",
        data: {num_give: num},
        success: function (response) {
            alert(response["msg"])
            window.location.reload()
        }
    });
}

 

↓완성본

 

**최종 수정 완성본**

4) 버킷리스트 완료 취소 API (Update→ POST)

  • 요청 정보 : URL = /bucket/dont
  • 요청 방식 : POST (update)
  • 클라(ajax) → 서버(flask) : num
  • 서버(flask) → 클라(ajax) : '취소완료' 메시지 보내기

↓서버 만들기

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

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

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

@app.route("/bucket", methods=["POST"])
def bucket_post():
    bucket_receive = request.form['bucket_give']

    bucket_list = list(db.bucket.find({},{'_id':False}))
    count = len(bucket_list) + 1

    doc = {
        'num':count,
        'bucket':bucket_receive,
        'done':0,
        'dont':1
    }
    db.bucket.insert_one(doc)

    return jsonify({'msg': '등록 완료!'})

@app.route("/bucket/done", methods=["POST"])
def bucket_done():
    num_receive = request.form['num_give']
    db.bucket.update_one({'num': int(num_receive)}, {'$set': {'done': 1}})
    db.bucket.update_one({'num': int(num_receive)}, {'$set': {'dont': 0}})
    return jsonify({'msg': '버킷 완료!'})

@app.route("/bucket/dont", methods=["POST"])
def bucket_dont():
    num_receive = request.form['num_give']
    db.bucket.update_one({'num': int(num_receive)}, {'$set': {'done': 0}})
    db.bucket.update_one({'num': int(num_receive)}, {'$set': {'dont': 1}})
    return jsonify({'msg': '취소 완료!'})

@app.route("/bucket", methods=["delete"])
def bucket_delete():
    num_receive = request.form['num_give']
    db.bucket.delete_one({'num': int(num_receive)})
    return jsonify({'msg': '삭제 완료!'})

@app.route("/bucket", methods=["GET"])
def bucket_get():
    bucket_list = list(db.bucket.find({}, {'_id': False}))
    return jsonify({'buckets': bucket_list})

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

 

↓HTML / CSS

<!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">

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
            crossorigin="anonymous"></script>

    <link href="https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap" rel="stylesheet">

    <title>인생 버킷리스트</title>

    <style>
        * {
            font-family: 'Gowun Dodum', sans-serif;
        }

        .mypic > h1 {
            font-size: 30px;
        }

        .mybox {
            width: 95%;
            max-width: 700px;
            padding: 20px;
            box-shadow: 0px 0px 4px 0px dimgray;
            margin: 20px auto;
        }

        .mybucket {
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
        }

        .mybucket > input {
            width: 80%;
        }

        .mybox > li {
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: center;

            margin-bottom: 10px;
            min-height: 48px;
        }

        .mybox > li > h2 {
            max-width: 75%;
            font-size: 20px;
            font-weight: 500;
            margin-right: auto;
            margin-bottom: 0px;
        }

        .done {
            text-decoration: line-through;
        }

        .todo-title {
            padding: 2rem;
            text-align: center;
            color: rosybrown;
            font-size: 5rem;
        }

        .MainBtn {
            border-radius: 4px;
            border-color: rosybrown;
            background-color: white;
            color: dimgrey;
        }

        .CheckBtn {
            border-radius: 4px;
            border-color: rosybrown;
            background-color: white;
            color: dimgrey;
        }

        .CheckBtn:hover {
            background-color: rosybrown;
            color: white;
        }

        .DontBtn {
            border-radius: 4px;
            border-color: lightsteelblue;
            background-color: white;
            color: dimgrey;
        }

        .DontBtn:hover {
            background-color: lightsteelblue;
            color: white;
        }

        .delBtn {
            border-radius: 4px;
            border-color: gray;
            background-color: white;
            color: rosybrown;
            font-weight: 900;
            margin-left: 6px;
        }

        .delBtn:hover {
            background-color: mistyrose;
            color: rosybrown;
        }

    </style>
    <script>
        $(document).ready(function () {
            show_bucket();
        });

        function show_bucket() {
            $.ajax({
                type: "GET",
                url: "/bucket",
                data: {},
                success: function (response) {
                    let rows = response['buckets']
                    for (let i = 0; i < rows.length; i++) {
                        let bucket = rows[i]['bucket']
                        let num = rows[i]['num']
                        let done = rows[i]['done']
                        let dont = rows[i]['dont']

                        let temp_html = ``

                        if (done == 0) {
                            temp_html = `<li>
                                <h2>🎵 ${bucket}</h2>
                                <button onclick="done_bucket(${num})" type="button" class="CheckBtn" >완료!
                                </button><button onclick="delete_bucket(${num})" class="delBtn">X</button>
                            </li>`
                        } else if (dont == 1) {
                            temp_html = `<li>
                                <h2>🎵 ${bucket}</h2>
                                <button onclick="done_bucket(${num})" type="button" class="CheckBtn" >완료!
                                </button><button onclick="delete_bucket(${num})" class="delBtn">X</button>
                            </li>`
                        } else {
                            temp_html = `<li>
                                <h2 class ="done">🎵 ${bucket}</h2>
                                <button onclick="dont_bucket(${num})" type="button" class="DontBtn" >취소</button>
                                </button><button onclick="delete_bucket(${num})" class="delBtn">X</button>
                            </li>`
                        }

                        $('#bucket-list').append(temp_html)
                    }
                }
            });
        }

        function save_bucket() {
            let bucket = $('#bucket').val()

            $.ajax({
                type: "POST",
                url: "/bucket",
                data: {bucket_give: bucket},
                success: function (response) {
                    alert(response["msg"])
                    window.location.reload()
                }
            });
        }

        function delete_bucket(num) {
            $.ajax({
                type: "delete",
                url: "/bucket",
                data: {num_give: num},
                success: function (response) {
                    alert(response["msg"])
                    window.location.reload()
                }
            });
        }

        function done_bucket(num) {
            $.ajax({
                type: "POST",
                url: "/bucket/done",
                data: {num_give: num},
                success: function (response) {
                    alert(response["msg"])
                    window.location.reload()
                }
            });
        }

        function dont_bucket(num) {
            $.ajax({
                type: "POST",
                url: "/bucket/dont",
                data: {num_give: num},
                success: function (response) {
                    alert(response["msg"])
                    window.location.reload()
                }
            });
        }

    </script>
</head>
<body>
<div class="todo-wrapper">
    <div class="todo-title">Bucket list</div>
    <div class="todo-box">

        <div class="mybox">
            <div class="mybucket">
                <input id="bucket" class="form-control" type="text" placeholder="이루고 싶은 것을 입력하세요">
                <button onclick="save_bucket()" type="button" class="MainBtn">기록하기</button>
            </div>
        </div>
        <div class="mybox" id="bucket-list">

        </div>
    </div>
</body>
</html>

 

 

**문제점 발견**

1. 버킷 리스트는 기입될 때 DB에 있는 버킷 리스트의 수 + 1 만큼의 넘버가 매겨진다.

ex. 앞선 리스트가 DB에 2개이면 현재 기입하는 리스트의 번호는 3번으로 지정됨

 

2. 삭제기능을 추가하다보니 여기서 첫번째 버킷을 지우게 되면 2개의 버킷이 남는데

   이때 새로운 버킷을 추가하면 DB에는 2개의 버킷 뿐이라 3번이라는 번호가 매겨진다.

 

3. 여기서 문제가 발생된다. 기존 남아있는 버킷의 번호는 2번과 3번으로 3번이 2개가 되어

삭제 및 완료 버튼을 누르게되면 먹지 않거나 다른게 삭제되는 버그가 발생이 되었다.

 

4. DB에 들어온 순서대로 번호가 매겨지는 등의 새로운 방법을 찾아야할거 같다..

   혹시 아시는분이 계시면 댓글을 부탁드립니다.