코딩 공부/스파르타 웹개발

스파르타 웹개발 종합반 - 4주차

잘자라는스투키 2021. 12. 18. 21:45
반응형

1. Flask

- API서버를 만들기 위해 자주 사용되는 Python의 마이크로 웹 프레임워크

- 패키지 설치 필요 : 파이참의 경우 file -> setting -> python interpreter

- 폴더생성 필요 : static(이미지,css파일) /tamplates(html파일)

- 기본 코드 : app.py

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)

- POST(API코드(서버)/Ajax코드(클라이언트))

@app.route('/test', methods=['POST']) #요청URL, 요청방식
def test_post():
   title_receive = request.form['title_give'] #요청데이터
   print(title_receive)
   return jsonify({'result':'success', 'msg': '이 요청은 POST!'}) #성공메세지
$.ajax({
    type: "GET",
    url: "/test?title_give=봄날은간다",
    data: {},
    success: function(response){
       console.log(response)
    }
  })

- GET(API코드(서버)/Ajax코드(클라이언트))

@app.route('/test', methods=['GET'])
def test_get():
   title_receive = request.args.get('title_give')  #요청데이터가 없는경우 없어도 됨
   print(title_receive)
   return jsonify({'result':'success', 'msg': '이 요청은 GET!'})  #응답데이터를 보내야함
$.ajax({
    type: "GET",
    url: "/test?title_give=봄날은간다",
    data: {},
    success: function(response){
       console.log(response)
    }
  })

2. PyMongo

- 파이썬에서 MongoDB제어하기 위해 사용하는 패키지

- 플라스크와 마찬가지로 패키지 설치 필요

 

3. 퀴즈 1

- 제목 저자 리뷰를 입력하면 아래 목록에 추가됨

- 예시 : http://spartacodingclub.shop/bookreview

- 서버 코드

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

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

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

## API 역할을 하는 부분
@app.route('/review', methods=['POST'])
def write_review():
    title_receive = request.form['title_give']
    name_receive = request.form['name_give']
    review_receive = request.form['review_give']

    doc = { 'title': title_receive,
            'name' : name_receive,
            'review' : review_receive
          }
    db.bookreview.insert_one(doc)
    return jsonify({'msg': '저장완료'})

@app.route('/review', methods=['GET'])
def read_reviews():
    reviews  = list(db.bookreview.find({}, {'_id': False}))

    return jsonify({'all_reviews' : reviews}) 


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

- 클라이언트

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

    <head>
        <!-- Webpage Title -->
        <title>모두의 책리뷰 | 스파르타코딩클럽</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 () {
                showReview();
            });

            function makeReview() {
                let title = $('#title').val()
                let name = $('#author').val()
                let review = $('#bookReview').val()

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

            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 temp_html =
                                 `<tr>
                                    <td>${reviews[i]['title']}</td>
                                    <td>${reviews[i]['name']}</td>
                                    <td>${reviews[i]['review']}</td>
                                 </tr>`
                            $('#reviews-box').append(temp_html);
                        }

                    }
                })
            }
        </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://previews.123rf.com/images/maxxyustas/maxxyustas1511/maxxyustas151100002/47858355-education-concept-books-and-textbooks-on-the-bookshelf-3d.jpg"
                 class="img-fluid" alt="Responsive image">
            <div class="info">
                <h1>읽은 책에 대해 말씀해주세요.</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="140자까지 입력할 수 있습니다."></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">

                    </tbody>
                </table>
            </div>
        </div>
    </body>

</html>

 

4. 퀴즈 2  

- 정보(url, review)를 입력하면 해당 url 메타태그에서 이미지와 설명, 제목을 추출하여 카드 목록에 추가함

- 스크랩핑 패키지 bs4이용 해야함

- 예시 : http://spartacodingclub.shop/

- 서버 코드

from flask import Flask, render_template, jsonify, request
import requests
from bs4 import BeautifulSoup

app = Flask(__name__)

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

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

## API 역할을 하는 부분
@app.route('/memo', methods=['POST'])
def write_review():

    url_receive = request.form["url_give"]
    review_receive = request.form["review_give"]

    #스크랩핑
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get(url_receive, headers=headers)

    soup = BeautifulSoup(data.text, 'html.parser')
    title_receive = soup.select_one('meta[property="og:title"]')['content']
    img_receive = soup.select_one('meta[property="og:image"]')['content']
    desc_receive = soup.select_one('meta[property="og:description"]')['content']

    doc = {
        "title" : title_receive,
        "img" : img_receive,
        "desc" : desc_receive,
        "review" : review_receive,
        "url" : url_receive
    }
    db.alonememo.insert_one(doc)
    return jsonify({'msg': '저장성공'})


@app.route('/memo', methods=['GET'])
def save_reviews():
    reviews = list(db.alonememo.find({}, {'_id' : False}))
    return jsonify({'all_reviews': reviews})


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

- 클라이언트

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

<head>
    <!-- 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="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@100&display=swap" rel="stylesheet">
    <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 first, 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>

    <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=Nanum+Pen+Script&display=swap" rel="stylesheet">

    <title>스파르타코딩클럽 | 부트스트랩 연습하기</title>
    <style>
        .wrap {
            width: 900px;
            margin: auto;
        }
        *{
          font-family: 'Nanum Pen Script', cursive;
        }
        .card-comment{
          color: blue;
          font-weight: bold;
        }
        .card-title{
          color: blue;

        }
        .form{
          width: 400px;
          margin: 30px auto 50px auto;
          margin-bottom: 50px;
          border: 30px solid black;
          padding : 30px;
          display : none;
        }
    </style>
    <script>
      $(document).ready(function(){
        $("#card-box").empty();
        listing();}
      );
      function listing() {
         $.ajax({
          type: "GET",
          url: "/memo",
          data: {},
          success: function(response){
              let memos = response['all_reviews']
              for(let i=0; i<memos.length; i++){
                let review = memos[i]['review']
                let title = memos[i]['title']
                let img = memos[i]['img']
                let url = memos[i]['url']
                let desc = memos[i]['desc']
                let temp_url = `<div class="card">
                                <img class="card-img-top" src="${img}" alt="Card image cap">
                                <div class="card-body">
                                  <a href = "${url}" class ="card-title">${title}</a>
                                  <p class="card-text">${desc}</p>
                                  <p class="card-comment">${review}</p>
                                </div>
                               </div>`
                 $("#card-box").append(temp_url);
              }

            }
          })
       }
       function saving_data() {

           $.ajax({
               type: "POST",
               url: "/memo",
               data: {
                   url_give: $('#inputurl').val(),
                   review_give: $('#review').val()
               },
               success: function (response) {
                   alert(response["msg"]);
               }
           })

       }
      function openclose(){
        let status = $('#post-box').css('display');
        console.log(status);
        if(status == 'block'){
          $('#post-box').hide();
          $('#btn-posting-box').text('포스팅 박스 열기');
        }else{
          $('#post-box').show();
           $('#btn-posting-box').text('포스팅 박스 닫기');
        }
      }
    </script>
</head>


    <body>
        <div class="wrap">
            <div class="jumbotron">
                <h1 class="display-4">나홀로 링크 메모장!</h1>
                <p class="lead">중요한 링크를 저장해두고, 나중에 볼 수 있는 공간입니다</p>
                <hr class="my-4">
                <p class="lead">
                    <button onclick="openclose()" id="btn-posting-box" type="button" class="btn btn-primary">포스팅 박스 열기
                    </button>
                </p>
            </div>
            <div id="post-box" class="form-post" style="display:none">
                <div>
                    <div class="form-group">
                        <label for="post-url">아티클 URL</label>
                        <input id="inputurl" class="form-control" placeholder="">
                    </div>
                    <div class="form-group">
                        <label for="post-comment">간단 코멘트</label>
                        <textarea id="review" class="form-control" rows="2"></textarea>
                    </div>
                    <button type="button" class="btn btn-primary" onclick="saving_data()">기사저장</button>
                </div>
            </div>
            <div id="card-box" class="card-columns">
            </div>
        </div>
    </body>

</html>

 

5. 최종과제

- 쇼핑몰 완성하기 : 정보 입력후 [주문하기]버튼을 누르면 주문목록에 추가되어 보여지기

- 예시  :  http://spartacodingclub.shop/homework

- 완성본 :

- 서버코드

from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

from pymongo import MongoClient

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


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


@app.route('/order', methods=['POST'])
def post_order():
    name_receive = request.form['name_give']
    quan_receive = request.form['quan_give']
    add_receive = request.form['add_give']
    ph_receive = request.form['ph_give']

    doc = {
        'name': name_receive,
        'quantity': quan_receive,
        'address': add_receive,
        'phone': ph_receive
    }

    db.orderdb.insert_one(doc)

    return jsonify({'result': 'success', 'msg': '저장완료'})


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


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

- 클라이언트코드 

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

<head>
    <!-- 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="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Nanum+Myeongjo&display=swap" rel="stylesheet">

    <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 first, 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>
    <style>
      *{
        font-family : 'Nanum Myeongjo', serif;
      }
      .wrap{
        width : 500px;
        margin : auto;      
      }
      .price{
        font-size : 5px;
      }
      .img{
         width : 500px;
         margin-bottom : 30px;
      }
      .input-group mb-3{
        margin : 10px;
      }
      .buy{
        width : 100px;
        margin : 30px auto 30px auto;
      }
      h1{
        font-weight : bold;
      }
     
    </style>
     <script>

      $(document).ready(function () {
            get_rate();
            orderlisting();
        });
        
      function get_rate(){
        $.ajax({
            type: "GET",
            url: "http://spartacodingclub.shop/sparta_api/rate",
            data: {},
            success: function(response){
              $('#rate').text(response['rate']);
              }
            })

      }

      function orderadd(){
        let name = $('#name').val()
        let quantity =$('#quantity').val()
        let address = $('#address').val()
        let phone =$('#phone').val()

        $.ajax({
                    type: "POST",
                    url: "/order",
                    data: {
                      name_give : name, 
                      quan_give: quantity,
                      add_give : address,
                      ph_give :phone
                      },
                    success: function (response)      {
                        alert(response["msg"]);
                         }
                   
                })

      }

      function orderlisting(){
        $.ajax({
            type: "GET",
            url: "/order",
            data: {},
            success: function(response){
                let orderlist= response["odlist"];
                for(let i=0; i < orderlist.length; i++){
                  let temp_html=  `<tr>
                                  <th scope="row">${orderlist[i]['name']}</th>
                                  <td>${orderlist[i]['quantity']}</td>
                                  <td>${orderlist[i]['address']}</td>
                                  <td>${orderlist[i]['phone']}</td>
                                </tr>`
                  $('#addlist').append(temp_html)
                }

            }
            })

      }
    </script>

</head>

<body>
    <h1></h1>
    <div class = "wrap">
      <img class ="img" src = "https://m.playwithscent.co.kr/web/product/big/202012/fa1d5c14f65b6e2771fb75486fe6da59.jpg"/>
      <h1>양초를 팝니다 <span style = "font-size:20px;">가격 :3000원/개</span></h1>
      <p>이 양초는 사실 특별한 힘을 지니고 있어요. 양초를 켜고 소원을 빌면 짜자잔 뭐든지 이뤄지게 된답니다. 하나 사가세요! 대나무향이 아주 좋아요.</p>
      <p style = "color : blue;">달러-원 환율 : <span id = "rate">  </span></p>
      <!-주문자이름-!>
      <div class="input-group mb-3">
      <div class="input-group-prepend">
      <span class="input-group-text" id="basic-addon1">주문자 이름</span>
      </div>
      <input type="text" class="form-control" aria-label="Username" aria-describedby="basic-addon1" id = "name">
      </div>

      <!-수량-!>
      <div class="input-group mb-3">
      <div class="input-group-prepend">
      <label class="input-group-text" for="inputGroupSelect01">수량</label>
      </div>
      <select class="custom-select" id="quantity">
      <option selected>수량을 선택하세요...</option>
      <option value="1" >One</option>
      <option value="2">Two</option>
      <option value="3">Three</option>
      </select>
      </div>
     
      <!-주소-!>
      <div class="input-group mb-3">
      <div class="input-group-prepend">
      <span class="input-group-text" id="basic-addon1">주소</span>
      </div>
      <input type="text" class="form-control" aria-label="Username" aria-describedby="basic-addon1" id= "address">
      </div>

      <!-전화번호-!>
      <div class="input-group mb-3">
      <div class="input-group-prepend">
      <span class="input-group-text" id="basic-addon1">전화번호</span>
      </div>
      <input type="text" class="form-control" aria-label="Username" aria-describedby="basic-addon1" id = "phone">
      </div>
      
      <!-주문하기-!>
      <div class = "buy">
      <button type="button" class="btn btn-light" onclick = "orderadd()">주문하기</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 = "addlist">
      </tbody>
      </table>
    </div>
</body>

</html> 

 -->

 

[스파르타 5만원 할인 받고 수강하세요!]

 

https://spartacodingclub.kr/?f_name=%EC%B5%9C%EB%AF%B8%EC%84%9C&f_uid=5f6fe706e482040009c7ec32

 

스파르타코딩클럽

왕초보 8주 완성! 웹/앱/게임 빠르게 배우고 내것을 만드세요!

spartacodingclub.kr

 

반응형