[11.02] 내일배움캠프[Spring] TIL-3

박상훈·2022년 11월 2일
0

내일배움캠프[TIL]

목록 보기
3/72

[11.02] 내일배움캠프[Spring] TIL-3

1. 미니 팀 프로젝트 진행

  • 어제까지의 진행 상황
    👉 각 회원들의 정보들을 알맞게 띄우고 방명록을 저장하여 띄워줬다.
  • 오늘 해야할 것
    1) 회원별 카드 클릭 시 정보를 보여주는 곳에서 디자인의 수정이 필요.
    2) 회원별 카드 클릭 시 정보를 보여주는 부분의 구조를 center정렬하자.
    3) 댓글에 삭제 기능을 구현하자.
    4) MongoDB에 저장된 상세 회원 정보를 알맞게 뿌려주자.
    5) 그 밖에도 디자인 적 요소를 추가 해보자.
  • 진행 된 코드( index.html )
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

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

    <title>Title</title>

    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@200;300;400;500;600;700;900&display=swap"
          rel="stylesheet">

    <style>

        * {
            font-family: 'Noto Serif KR', serif;
        }

        .member_content {
            display: flex;
            flex-direction: column;
              align-items: center;
            justify-content: center;

        }

        .top_content {
            width: 100%;
            height: 400px;

            background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('https://coresos-phinf.pstatic.net/a/30hbb6/0_cf7Ud018svcavwo8ineb9ww_oya09y.jpg?type=cover_a640');
            background-position: center;


            color: white;

            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }

        .profile {
            display: flex;
            flex-direction: row;
            margin: 30px auto 0px auto;
            width: 95%;
            max-width: 900px;
            border-radius: 30px;


        }

        .visitor > button {

            width: 200px;
            height: 50px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;


            background-color: transparent;
            border-radius: 50px;
            border: 1px solid;
            margin: 10px auto 10px auto;


        }

        .visitor {


           display: flex;
            flex-direction: column;
            display: none;

        }

        .mypost {
            width: 95%;
            max-width: 500px;
            margin: 20px auto 20px auto;

            box-shadow: 0px 0px 3px 0px black;
            padding: 20px;
            display: none;


        }

        .mypost > button {
            margin-top: 15px;
        }

        /*회원 상세페이지 사진 크기*/
        .col-md-4 > img {
            width: 800px;
            height: 400px;
        }

        /*메인 페이지 이름이랑 간단소개 까맣게 하는 부분*/
        .card-body1 {
            background-color: black;
            color: white;
        }


        .card {
            width: 95%;
            max-width: 500px;
            margin: auto;
        }

        #card_borer{
            border: 5px solid red;
        }


    </style>

    <script>
        //각 회원 프로필 넘어가는 부분
        $(document).ready(function () {
            show_members();
        });

        function show_members() {
            $('#mypost').hide()
            alert('조회')


            $.ajax({
                type: "GET",
                url: "/home",
                data: {},
                success: function (response) {
                    let rows = response['members']


                    for (let i = 0; i < rows.length; i++) {
                        let name = rows[i]['name']
                        let comment = rows[i]['comment']
                        let img = rows[i]['img']

                        let temp_html = `<div class="col">
                                            <div class="card h-100" id="card_borer"token interpolation">${name}')">
                                                <img src="${img}" class="card-img-top" alt="..." width="300px" height="300px">
                                                <div class="card-body1">
                                                    <h5 class="card-title">${name}<img src="../static/Group2.png"></h5>
                                                    <p class="card-text">${comment}</p>
                                                </div>
                                            </div>
                                        </div>`


                        $('#members').append(temp_html)
                    }
                }
            });
        }

        function member_post(name) {

            $.ajax({
                type: "POST",
                url: '/one-post',
                data: {name_give: name},


                success: function (response) {

                    $('#members').empty()
                    $('#member_detail').empty()
                    $('#card').empty()
                    let rows = response['member']

                    let name = rows['name']
                    let comment = rows['comment']
                    let img = rows['img']
                    let detail = rows['detail']

                    let temp_html = `<div class="col-md-4">
                                             <img src="${img}" class="img-fluid rounded-start" alt="...">
                                          </div>
                                                <div class="col-md-8">
                                                  <div class="card-body">
                                                    <h5 class="card-title">${name}</h5>
                                                    <p class="card-text">${detail}</p>
                                                    <p class="card-text"><small class="text-muted">${comment}</small></p>
                                                  </div>
                                                </div>`


                    $('#member_detail').append(temp_html)
                    $('#mypost').show()
                    $('#hidden_name_val').attr('value', name)
                    $('#visitor').show()

                    let rows_bang = response['members_bang_list']
                    for (let i = 0; i < rows_bang.length; i++) {
                        let nick_name = rows_bang[i]['nick_name']
                        let comment = rows_bang[i]['comment']

                        let temp_html = `<div class="card-body">
                                            <blockquote class="blockquote mb-0">
                                              <p>${comment}</p>
                                              <footer class="blockquote-footer">${nick_name}<cite title="Source Title"></cite></footer>
                                              <buttontoken interpolation">${nick_name}')" type="button" class="btn btn-outline-primary">삭제</button>
                                            </blockquote>`

                        $('#card').append(temp_html)
                    }
                    $('#comment').val('')
                    $('#nick_name').val('')

                }
            });
        }

        function save_comment() {

            let name = $('#hidden_name_val').val()
            let comment = $('#comment').val()
            let nick_name = $('#nick_name').val()
            alert(name)

            $.ajax({
                type: 'POST',
                url: '/homework',
                data: {
                    name_give: name,
                    comment_give: comment,
                    nick_name_give: nick_name
                },
                success: function (response) {
                    alert(response['msg'])
                    member_post(name)
                }
            })
        }

        function open_box() {
            $('#post-box').show()
        }

        function close_box() {
            $('#post-box').hide()
        }

        function del_comment(nick_name) {
            let name = $('#hidden_name_val').val()
            $.ajax({
                type: "POST",
                url: "/homework/del",
                data: {nick_name_give: nick_name},
                success: function (response) {
                    alert(response["msg"])
                    member_post(name)
                }
            });
        }

    </script>
</head>
<body>

<div class="top_content">
    <h1>6789땡</h1>
    <img src="../static/Group2.png">
</div>


<div class="profile" id="profile2">

    <div class="row row-cols-1 row-cols-md-3 g-4" id="members">

    </div>

</div>

<div class="member_content">

    <div class="card mb-3" style="max-width: 1000px;">
        <div class="row g-0" id="member_detail">

        </div>


    </div>

    <div class="col-md-6">
        <div class="visitor" id="visitor">
            <button onclick="open_box()">방명록 남기기</button>
        </div>

        <div class="mypost" id="post-box">

            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="nick_name" placeholder="url">
                <label for="floatingInput">닉네임</label>
            </div>

            <div class="form-floating">
            <textarea class="form-control" placeholder="Leave a comment here" id="comment"
                      style="height: 100px"></textarea>
                <label for="floatingTextarea2">응원댓글</label>
            </div>
            <input id="hidden_name_val" type="hidden" value="">
            <button onclick="save_comment()" type="button" class="btn btn-dark">응원 남기기</button>
            <button onclick="close_box()" type="button" class="btn btn-outline-dark">닫기</button>
        </div>
    </div>


</div>

<div class="card" id="card">

</div>

</body>
</html>
  • app.py
from flask import Flask, render_template, request, jsonify, redirect, url_for
from pymongo import MongoClient


app = Flask(__name__)

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

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

@app.route("/home", methods=["GET"])
def members_get():
    member_list = list(db.members.find({},{'_id':False}))

    return jsonify({'members': member_list})

@app.route("/one-post", methods=["POST"])
def one_post():
    name_receive = request.form['name_give']
    member = db.members.find_one({'name': name_receive}, {'_id': False})
    members_bang_list = list(db.members_bang.find({'name': name_receive}, {'_id': False}))
    print(members_bang_list)
    # return redirect(url_for('one_get', name = name_receive))
    return jsonify({'member': member,
                    'members_bang_list': members_bang_list
                    })


@app.route("/homework", methods=["POST"])
def save_comment():
    name_receive = request.form['name_give']
    comment_receive = request.form['comment_give']
    nick_name_receive = request.form['nick_name_give']

    doc = {
        'name': name_receive,
        'comment': comment_receive,
        'nick_name': nick_name_receive
    }

    db.members_bang.insert_one(doc)


    return jsonify({'msg':'저장 완료!'})

@app.route("/homework/del", methods=["POST"])
def homework_del():
    nick_name_receive = request.form['nick_name_give']

    db.members_bang.delete_one({'nick_name': nick_name_receive})
    return jsonify({'msg':'삭제완료!'})

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)
  • 오늘까지의 결과물

2. 결과물에 대한 정리

👉 전체 회원 페이지의 화투장 이미지를 더하기 위해 검은 배경,빨간선 추가.
👉 회원 상세 페이지의 구조 정렬.
👉 회원 상세 페이지의 알맞은 DB 뿌려주기.
👉 댓글을 저장하고 삭제하는 기능 구현.

3. 진행 애로사항과 해결

1) 댓글을 남기고 저장한 후 입력 값이 아직 input창에 존재했다.

<div class="mypost" id="post-box">

            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="nick_name" placeholder="url">
                <label for="floatingInput">닉네임</label>
            </div>

            <div class="form-floating">
            <textarea class="form-control" placeholder="Leave a comment here" id="comment"
                      style="height: 100px"></textarea>
                <label for="floatingTextarea2">응원댓글</label>
            </div>
 $('#comment').val('')
 $('#nick_name').val('')

👉 회원별 상세 정보 페이지는 저장 로직을 걸친 후 다시 호출 되므로
id 값을 긁어와 공백으로 초기화 하였다.

2) 댓글을 남기거나 댓글을 삭제한 후 , 메인 창이 아닌 상세정보창을 로드하고 싶다.

 $('#members').empty()
 $('#member_detail').empty()
 $('#card').empty()

 member_post(name) //재호출 부분!

👉 삭제나 저장 작업이 끝난 후 회원 정보를 뿌려주는 member_post(name) 을 재 호출 했다.
👉 이 때 , 기존에 삭제나 저장을 하기 전에 뿌려준 부분과 중복 되어
두번 출력이 되는 것을 방지하기 위해 empty()메서드를 사용하여 기존 걸
지우고 새로 다시 출력 하도록 조치했다.

3) 댓글 삭제기능 구현 시 중복되지 않는 구별 값 필요!

function del_comment(nick_name) {
            let name = $('#hidden_name_val').val()
            $.ajax({
                type: "POST",
                url: "/homework/del",
                data: {nick_name_give: nick_name},
                success: function (response) {
                    alert(response["msg"])
                    member_post(name)
                }
            });
        }
@app.route("/homework/del", methods=["POST"])
def homework_del():
    nick_name_receive = request.form['nick_name_give']

    db.members_bang.delete_one({'nick_name': nick_name_receive})
    return jsonify({'msg':'삭제완료!'})

👉 사전 캠프 때는 삭제 기능 구현 시 id 값으로 댓글의 총 갯수+1로 고유 값을 부여했는데, 만약 중간 게시글의 삭제 후 새로운 댓글이 추가 된다면,게시글의 마지막 id값이 중복되게 된다.

👉 본 프로젝트에서는 댓글의 닉네임이 중복되지 않는 다는 가정하에
닉네임으로 판별하여 댓글을 지우는 시스템을 구축했다.

👉 만약 더 확실한 삭제 기능을 구현하고 싶다면, mongoDB에서 DB추가시 고유하게 생성되는 ObjectID를 활용하면 될 것 같다.

4. 느낀점⭐

1) css를 건드릴 때는 어디까지 테그가 걸려있는지 잘 파악하자.
2) MongoDB의 ObjectID를 가져다 쓰는 작업을 해보고 싶다.

profile
기록하는 습관

0개의 댓글