[스파르타] 원페이지 쇼핑몰 완성하기(feat. Flask, mongodb)

장만옥·2021년 8월 11일
0

스파르타 코딩클럽 4주차 수강을 완료했다!
이제 5주차만 남겨두고 있는데, 처음 시작할때는 내가 그래도 조금 알고 있던 것들을 튜터가 얘기해주면서 재미있게 시간가는줄 모르고 들었다
2주차 지나가면서부터 회사 일도 바빠지고 많아지고
매일 노트북 들고 다니면서 핫스팟 연결해서 틈틈히 수업듣던 시간들이 얼마안된 것 같은데 벌써 숙제를 4개나 했다!
물론 강의해설도 봤고 수업에서 힌트도 많이 나와서 조금만 시간 투자하면 금방 할수있다(나도 했는걸)
거두절미하고 이번 4주차에는 서버와 서버 연결, API만들기를 배웠다

[flask 패키지를 설치하고 서버를 만들어본다]

서버란?
우리는 컴퓨터가 한 대 잖아요... 그래서 같은 컴퓨터에다 서버도 만들고, 요청도 할 거예요. 즉, 클라이언트 = 서버가 되는 것이죠.
이것을 바로 "로컬 개발환경"이라고 한답니다!
일단 폴더 4개를 만들고 시작해야 한다

  • prac: "flask 연습 코드를 작성합니다." (오늘)
  • alonememo : "나홀로메모장" 관련 코드를 작성합니다. (오늘)
  • bookreview : "모두의책리뷰" 관련 코드를 작성합니다. (오늘)
  • moviestar : "마이페이보릿무비스타" 관련 코드를 작성합니다. (5주차)
    난 아직도 폴더 만드는 부분이 가장 어렵다 ㅠ
    만든 폴더를 파이참에서 찾는 것도 어렵고 ㅠ

flask 패키지 깔기

리마인드! 패키지 설치 화면 진입하기

윈도우 : 좌상단File → setting → Python interpreter
맥 : 좌상단Pycharm → Preference → Python Interpreter

  • 3) Flask 기초: 기본 실행
    - Flask 프레임워크: 서버를 구동시켜주는 편한 코드 모음. 서버를 구동하려면 필요한 복잡한 일들을 쉽게 가져다 쓸 수 있습니다.

        프레임워크를 쓰지 않으면 태양초를 빻아서 고추장을 만드는 격!
        프레임워크는 3분 요리/소스 세트라고 생각하면 되겠습니다!
    
    - [app.py](http://app.py) 파일을 만들어 아래 코드를 붙여넣어봅니다.
    
        파일 이름은 아무렇게나 해도 상관없지만,
        통상적으로 flask 서버를 돌리는 파일은 app.py라고 이름 짓습니다!
    
        - **[코드스니펫] - flask 시작 코드**
    
            ```python
            from flask import Flask
            app = Flask(__name__)
    
            @app.route('/')
            def home():
               return 'This is Home!'
    
            if __name__ == '__main__':  
               app.run('0.0.0.0',port=5000,debug=True)
            ```
    
    - 오른쪽 클릭 → '`Run app`'을 클릭하고, 터미널에 아래와 같은 메시지가 뜨면 실행 성공!
    
        ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/355eb768-0a48-48ff-9cc7-079bbeb696a9/Untitled.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/355eb768-0a48-48ff-9cc7-079bbeb696a9/Untitled.png)
    
    - 이제 크롬에서 [http://localhost:5000](http://localhost:5000)/ 으로 접속해보세요.
    
        화면에 `Hello World!` 라는 메시지가 보이시나요? 그렇다면 성공한 것! 👏
    
    - 종료하는 방법
    
        터미널 창을 클릭하시고, ctrl + c 을 누르시면 서버를 종료할 수 있습니다.
        html 파일을 불러오는 방법 
        **templates 폴더의 역할을 알아보겠습니다.**

    HTML 파일을 담아두고, 불러오는 역할을 하죠!

  1. 간단한 index.html 파일을 templates 안에 만들기

    • [코드스니펫] index.html 예제코드

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
          <title>Document</title>
      </head>
      <body>
          <h1>서버를 만들었다!</h1>
      </body>
      </html>
  2. html 파일 불러오기

    flask 내장함수 render_template를 이용합니다. 바로 이게 프레임워크의 위력!

    from flask import Flask, render_template
    app = Flask(__name__)
    
    ## URL 별로 함수명이 같거나,
    ## route('/') 등의 주소가 같으면 안됩니다.
    
    @app.route('/')
    def home():
       return render_template('index.html')
    
    if __name__ == '__main__':
       app.run('0.0.0.0', port=5000, debug=True)

api설계하기

  • 18) 프로젝트 설계 - 만들 API 설계

    포스팅API - 카드 생성 (Create)

    A. 요청 정보

    • 요청 URL= /memo , 요청 방식 = POST

    • 요청 데이터 : URL(url_give), 코멘트(comment_give)

      B. 서버가 제공할 기능

    • URL의 meta태그 정보를 바탕으로 제목, 설명, 이미지URL 스크래핑

    • (제목, 설명, URL, 이미지URL, 코멘트) 정보를 모두 DB에 저장

      C. 응답 데이터

    • API가 정상적으로 작동하는지 클라이언트에게 알려주기 위해서 성공 메시지 보내기

    • (JSON 형식) 'result'= 'success'

      리스팅API - 저장된 카드 보여주기 (Read)

      A. 요청 정보

    • 요청 URL= /memo , 요청 방식 = GET

    • 요청 데이터 : 없음

      B. 서버가 제공할 기능

    • DB에 저장돼있는 모든 (제목, 설명, URL, 이미지URL, 코멘트) 정보를 가져오기

      C. 응답 데이터

    • 아티클(기사)들의 정보(제목, 설명, URL, 이미지URL, 코멘트) → 카드 만들어서 붙이기

    • (JSON 형식) 'articles': 아티클 정보

나홀로쇼핑몰에 '주문하기''주문내역보기' 기능 만들기

  • 18) 프로젝트 설계 - 만들 API 설계

    포스팅API - 카드 생성 (Create)

    A. 요청 정보

    • 요청 URL= /memo , 요청 방식 = POST

    • 요청 데이터 : URL(url_give), 코멘트(comment_give)

      B. 서버가 제공할 기능

    • URL의 meta태그 정보를 바탕으로 제목, 설명, 이미지URL 스크래핑

    • (제목, 설명, URL, 이미지URL, 코멘트) 정보를 모두 DB에 저장

      C. 응답 데이터

    • API가 정상적으로 작동하는지 클라이언트에게 알려주기 위해서 성공 메시지 보내기

    • (JSON 형식) 'result'= 'success'

      리스팅API - 저장된 카드 보여주기 (Read)

      A. 요청 정보

    • 요청 URL= /memo , 요청 방식 = GET

    • 요청 데이터 : 없음

      B. 서버가 제공할 기능

    • DB에 저장돼있는 모든 (제목, 설명, URL, 이미지URL, 코멘트) 정보를 가져오기

      C. 응답 데이터

    • 아티클(기사)들의 정보(제목, 설명, URL, 이미지URL, 코멘트) → 카드 만들어서 붙이기

    • (JSON 형식) 'articles': 아티클 정보
      app.py 서버
      from flask import Flask, render_template, jsonify, request

app = Flask(name)

from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.dbhomework

HTML 화면 보여주기

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

주문하기(POST) API

@app.route('/order', methods=['POST'])
def save_order():
name_receive = request.form['name_give']
count_receive = request.form['count_give']
address_receive = request.form['address_give']
phone_receive = request.form['phone_give']

doc = {
    'name': name_receive,
    'count': count_receive,
    'address': address_receive,
    'phone': phone_receive,

}
db.orders.insert_one(doc)

return jsonify({'result': 'success', 'msg': '주문이 완료되었습니다!'})

주문 목록보기(Read) API

@app.route('/order', methods=['GET'])
def view_orders():
orders = list(db.orders.find({}, {'_id': False}))
return jsonify({'result': 'success', 'orders': orders})

if name == 'main':
app.run('0.0.0.0', port=5000, debug=True)

1주차 때 만든 원페이지 쇼핑몰 html 페이지에 주문하기 기능을 업데이트 하면 이렇게 나온다

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

<!-- Optional JavaScript -->
<!-- jQuery hj0000first, then Popper.js, then Bootstrap 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>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"></script>

<title>만옥이네 장터 | 쇼핑몰페이지 연습하기</title>

<link href="<link rel=" preconnect
" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="<link rel=" preconnect
" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300&display=swap" rel="stylesheet">


<style>
    * {
        font-family: 'Noto Sans KR', sans-serif;
    }

    .item-img {
        width: 500px;
        height: 300px;

        background-image: url("https://openinnovation.co.kr/data/bbsData/1614223239&&%ED%8C%94%EC%BD%98%20%EC%9D%B4%EB%85%B8%EB%B2%A0%EC%9D%B4%EC%85%981.jpg");
        background-position: center;
        background-size: cover;
        margin-top: 25px;
    }

    .price {
        font-size: 15px;
    }

    .item-desc {
        width: 500px;
        margin-top: 20px;
        margin-bottom: 20px;
    }

    .item-order {
        width: 500px;
        margin-bottom: 20px;
    }

    .btn-order {
        margin: auto;
        width: 100px;

        display: block;
    }

    .wrap {
        width: 500px;
        margin: auto;
    }

    .rate {
        color: red;
    }


</style>

<script>
    $(document).ready(function () {
        get_rate();
        listing();
    });

    function listing() {
        $.ajax({
            type: "GET",
            url: "/order",
            data: {},
            success: function (response) {
                if (response["result"] == "success") {
                    let orders = response['orders'];
                    for (let i = 0; i < orders.length; i++) {
                        let name = orders[i]['name'];
                        let count = orders[i]['count'];
                        let address = orders[i]['address'];
                        let phone = orders[i]['phone'];

                        let temp_html = `<tr>
                                                <th scope="row">${name}</th>
                                                <td>${count}</td>
                                                <td>${address}</td>
                                                <td>${phone}</td>
                                            </tr>`
                        $('#orders-box').append(temp_html)
                    }

                }
            }
        })
    }

    function get_rate() {
        $.ajax({
            type: "GET",
            url: "https://api.manana.kr/exchange/rate.json",
            data: {},
            success: function (response) {
                let now_rate = response[1]['rate'];
                $('#now-rate').text(now_rate);
            }
        })
    }

    function order() {
        let name = $('#order-name').val();
        let count = $('#order-count').val();
        let address = $('#order-address').val();
        let phone = $('#order-phone').val();

        $.ajax({
            type: "POST",
            url: "/order",
            data: {name_give: name, count_give: count, address_give: address, phone_give: phone},
            success: function (response) {
                if (response["result"] == "success") {
                    alert(response["msg"]);
                    window.location.reload();
                }
            }
        })
    }

</script>

만옥이네 장터 판매가: 380만원/대(VAT별도)

안면인식 발열감지 시스템 열화상카메라 팔콘 에이아이 ! !

개인정보보호 수칙에 따른 열화상카메라 팔콘 에이아이로 방역에 앞장서세요! 팔콘 에이아이는 코로나가 종식된 이후에도 직원출입관리 솔루션으로도 활용이 가능합니다.

달러-원 환율 : 1155.27

</div>
<div class="item-order">
    <div class="input-group mb-3">
        <div class="input-group-prepend">
            <span class="input-group-text">주문자 이름</span>
        </div>
        <input id="order-name" type="text" class="form-control" aria-label="Default"
               aria-describedby="inputGroup-sizing-default">
    </div>
    <div class="input-group mb-3">
        <div class="input-group-prepend">
            <label class="input-group-text" for="inputGroupSelect01">주문 수량</label>
        </div>
        <select id="order-count" class="custom-select">
            <option selected>-- 수량을 선택하세요 --</option>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
            <option value="5">5</option>
            <option value="10대 이상">10대 이상</option>
        </select>
    </div>
    <div class="input-group mb-3">
        <div class="input-group-prepend">
            <span class="input-group-text">주소</span>
        </div>
        <input id="order-address" type="text" class="form-control" aria-label="Default"
               aria-describedby="inputGroup-sizing-default">
    </div>
    <div class="input-group mb-3">
        <div class="input-group-prepend">
            <span class="input-group-text">연락처</span>
        </div>
        <input id="order-phone" type="text" class="form-control" aria-label="Default"
               aria-describedby="inputGroup-sizing-default">
    </div>
    <button type="button" onclick="order()" class="btn btn-primary btn-order">주문하기</button>
</div>
<table class="table">
    <thead>
    <tr>
        <th scope="col">이름</th>
        <th scope="col">수량</th>
        <th scope="col">주소</th>
        <th scope="col">연락처</th>
    </tr>
    </thead>
    <tbody id = "orders-box">
    </tbody>
</table>
``` ![](https://velog.velcdn.com/images%2Folivia_kim%2Fpost%2F3f9f9571-cc1e-4cf5-b7fe-caf84092c5b2%2Fimage.png) 처음에는 환율 부분이 색깔이 안먹혔는데, ajax에서 오류가 발생했었다 계속 보는데도 모르겠어서 천천히 다시 보니까 잘못된 느낌이 드는 곳을 고쳤더니 신기하게 됐다 이게 코딩의 매력인것인가..? 신기하다
profile
마케터 만옥이 개발일지

0개의 댓글