본문 바로가기
항해99

[항해99 온보딩]웹개발 종합반 4주차

by 지 요니 2023. 3. 23.

1. Flask

  • 로컬 개발환경(클라이언트 = 서버)

  • Flask 폴더 구조
prac 폴더 구조
- - -
prac
|— venv  (가상 환경) => python -m venv venv
|— app.py (서버)
|— templates
         |— index.html (클라이언트 파일)
  • Flask 서버를 만들 땐 항상, 프로젝트 폴더 안에, 
    • templates 폴더(html파일 담아두고 불러오는 역할)
    • app.py 파일
  • Flask 프레임워크: 서버를 구동시켜주는 편한 코드 모음, 즉 웹 서버를 구동하는데 필요한 복잡한 코드를 쉽게 가져다 쓸 수 있다!
  • Flask 시작 코드
#기본 뼈대
from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
   return 'This is Home!'
   
@app.route('/mypage')
def mypage():
	return '<button>나는 버튼!</button>

if __name__ == '__main__':  
   app.run('0.0.0.0',port=5000,debug=True)
@app.route('/') 부분을 수정해서 URL을 나눌 수 있다!
위 코드에서 @app.route('/')와 @app.route('/')처럼!!

단, - url 별로 함수명이 같거나,
    - `route('/')`내의 주소가 같으면 안된다!
  • html파일 불러오기 → flask 내장함수 render_template를 이용
from flask import Flask, render_template

@app.route('/mypage')
def mypage():

   return render_template('index.html')
  • 클라이언트가 서버에 요청할 때 HTTP방식
    1. GET 요청: 통상적으로 데이터 조회(Read)를 요청할때 사용
      • 데이터 전달: URL뒤에 물음표를 붙여 key=value로 전달
      • 예) 영화 목록 조회
    2. POST 요청: 통상적으로 데이터 생성(Create), 변경(Update), 삭제(Delete) 요청 할 때 사용
      • 데이터 전달: 바로 보이지 않는 HTML
      • 예) 회원가입, 회원탈퇴, 비밀번호 수정
  • GET 요청 API코드
@app.route('/test', methods=['GET'])
def test_get():
   title_receive = request.args.get('title_give')
   print(title_receive)
   return jsonify({'result':'success', 'msg': '이 요청은 GET!'})
  • GET 요청 확인 Fetch 코드
fetch("/test").then(res => res.json()).then(data => {
		console.log(data)
})
  • POST 요청 API코드
@app.route('/test', methods=['POST'])
def test_post():
   title_receive = request.form['title_give']
   print(title_receive)
   return jsonify({'result':'success', 'msg': '이 요청은 POST!'})
  • POST 요청 확인 Fetch코드
let formData = new FormData();
formData.append("title_give", "블랙팬서");

fetch("/test", { method: "POST", body: formData }).then(res => res.json()).then(data => {
    console.log(data)
})

2. 미니 프로젝트1[화성땅 공동구매]

  • POST연습:주문 저장(이름, 주소, 평수 저장 → CREATE이므로 POST방식)

1) 데이터 명세

  1. 요청 정보 : URL= /mars, 요청 방식 = POST
  2. 클라(fetch) → 서버(flask) : name, address, size
  3. 서버(flask) → 클라(fetch) : 메시지를 보냄 (주문 완료!)

2) 클라이언트와 서버 연결 확인하기

3) 서버부터 만들기(app.py)

#데이터베이스에 연결
from pymongo import MongoClient

client = MongoClient('내 URL')
db = client.dbsparta
#name, address, size 정보 받아서 저장
@app.route("/mars", methods=["POST"])
def mars_post():
    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': '주문 완료!'})

4) 클라이언트 만들기(index.html)

#name, address, size정보 보내주기
function save_order() {
        let name = $("#name").val()
        let address = $("#address").val()
        let size = $("#size").val()

        let formData = new FormData()
        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) => {
            alert(data["msg"])
            window.location.reload()
          });
      }

5) 완성 확인하기 → 데이터 입력 후 DB에 잘 들어갔는지 확인

  • GET연습:주문 보여주기(저장된 주문 화면에 보여주기 → READ이므로 GET방식)

1) 데이터 명세

  1. 요청 정보 : URL= /mars, 요청 방식 = GET
  2. 클라(fetch) → 서버(flask) : 없음
  3. 서버(flask) → 클라(fetch) : 전체 주문을 보내주기

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

3) 서버부터 만들기

#result에 주문정보 담아서 내려주기
@app.route("/mars", methods=["GET"])
def mars_get():
    mars_data = list(db.mars.find({},{'_id':False}))
    return jsonify({'result':mars_data})

4) 클라이언트 만들기

#주문정보: 리스트 형식 => forEach문으로 반복해서 데이터 뽑아내기
function show_order() {
        fetch('/mars').then((res) => res.json()).then((data) => {
            let rows = data['result']
						$("#order-box").empty()
	            rows.forEach((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)
            })
          })
      }

5) 완성 확인하기 → 화면 새로고침했을 때, DB에 저장된 리뷰가 화면에 잘 나타나는지 확인

미니 프로젝트1 완성 화면

3. 미니 프로젝트2[스파르타피디아]

  • 조각 기능flask 라이브러리를 사용하지 않는 기능이 있을 시에 app.py밖에서 기능 구현
    • 장점: 일일히 테스트할 때 flask에서 브라우저를 열지 않아 더 빠름!
    • app.py말고 다른 파일 만든 후에 코드 작업 성공시 복사해 app.py로 가져오기
    • 예시) meta 태그 정보 가져오는 조각기능 만들기

* meta 태그? 눈에 보이는 것 이외의 웹의 속성을 설명해주는 태그

meta 태그 예시(썸네일 사진, 제목, 설명 ..)

 

import requests
from bs4 import BeautifulSoup

url = 'https://movie.naver.com/movie/bi/mi/basic.naver?code=191597'

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,headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')

ogtitle = soup.select_one('meta[property="og:title"]')['content']
ogdesc = soup.select_one('meta[property="og:description"]')['content']
ogimage = soup.select_one('meta[property="og:image"]')['content']

print(ogimage,ogtitle,ogdesc)

  • POST연습: 포스팅하기

1) 데이터 명세

  1. 요청 정보 : URL= /movie, 요청 방식 = POST
  2. 클라(fetch) → 서버(flask) : url, comment
  3. 서버(flask) → 클라(fetch) : 메시지를 보냄 (포스팅 완료!)

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

3) 서버부터 만들기

@app.route("/movie", methods=["POST"])
def movie_post():	#URL, comment 정보 받아서 저장
    url_receive = request.form['url_give']
    comment_receive = request.form['comment_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')

    ogimage = soup.select_one('meta[property="og:image"]')['content']
    ogtitle = soup.select_one('meta[property="og:title"]')['content']
    ogdesc = soup.select_one('meta[property="og:description"]')['content']


    doc = {
        'image':ogimage,
        'title':ogtitle,
        'desc':ogdesc,
        'comment':comment_receive
    }

    db.movies.insert_one(doc)

    return jsonify({'msg':'포스팅 완료!'})

4) 클라이언트 만들기

#url, comment정보 내보내기
function posting() {	
            let url = $('#url').val()
            let comment = $('#comment').val()

            let formData = new FormData()
            formData.append('url_give', url)
            formData.append('comment_give', comment)

            fetch('/movie', {method: "POST",body: formData}).then(res => res.json()).then(data => {
                    alert(data['msg'])
                    window.location.reload()	#화면 새로고침
                })
        }

5) 완성 확인하기 → DB에 잘 들어갔는지 확인

 

  • GET연습: 포스트 보여주기

1) 데이터 명세

  1. 요청 정보 : URL= /movie, 요청 방식 = GET
  2. 클라(fetch) → 서버(flask) : 없음
  3. 서버(flask) → 클라(fetch) : 전체 주문을 보내주기

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

3) 서버부터 만들기

#orders에 주문정보 담아 내려주기
@app.route("/movie", methods=["GET"])
def movie_get():
    all_movies = list(db.movies.find({},{'_id':False}))
    return jsonify({'result':all_movies})

4) 클라이언트 만들기

#주문정보는 리스트형식 => forEach문으로 반복하면서 데이터 뽑아내기
function listing() {
            fetch('/movie').then(res => res.json()).then(data => {
                    let rows = data['result']
				            $('#cards-box').empty()
                    rows.forEach((a) => {
												let comment = a['comment']
                        let title = a['title']
                        let image = a['image']
                        let desc = a['desc']

                        let temp_html = `<div class="col">
                                            <div class="card h-100">
                                                <img src="${image}"
                                                     class="card-img-top">
                                                <div class="card-body">
                                                    <h5 class="card-title">${title}</h5>
                                                    <p class="card-text">${desc}</p>
                                                    <p class="mycomment">${comment}</p>
                                                </div>
                                            </div>
                                        </div>`

                        $('#cards-box').append(temp_html)
                    })
                })
        }

5) 완성 확인하기 → 화면 새로고침했을 때, DB에 저장된 리뷰가 화면에 잘 나타나는지 확인

 

  • 숙제: 스파르타피디아에 별점 넣는 기능 추가

별점을 주면 값을 숫자로 넣고 DB에 저장(POST) → 포스트를 보여주면 별점의 숫자만큼 별 표시

# index.html에 별점 추가
<div class="input-group mb-3">
    <label class="input-group-text" for="inputGroupSelect01">별점</label>
    <select class="form-select" id="star">
        <option selected>-- 선택하기 --</option>
        <option value="1">⭐</option>		#별점마다 value 속성 값 들어있음 
        <option value="2">⭐⭐</option>
        <option value="3">⭐⭐⭐</option>
        <option value="4">⭐⭐⭐⭐</option>
        <option value="5">⭐⭐⭐⭐⭐</option>
    </select>
</div>

* 숫자를 별로 표시(숫자만큼 ⭐️반복하기)

let start = a['star']
let star_repeat = '⭐'.repeat(star)

- POST: 별점 등록하기

  • 클라이언트
#기존 POST 요청에 별의 값을 가져오기
let star = $('#star').val()

#값을 formData에 넣고 append
formData.append("star_give", star)
  • 서버
#값 받기
star_receive = request.form['star_give']

#데이터베이스에 저장할 값에 star_receive 넣기
doc = {
        'image':image,
        'title':title,
        'desc':description,
        'star':star_receive,
        'comment':comment_receive
    }

- GET: 별점 보여주기

  • 서버: 변동X
  • 클라이언트
#data에서 star 값 찾기
let star = a['star']

#star 값을 별 모양으로 표시
              let star_repeat = "⭐".repeat(star);

              let temp_html = `<div class="col">
                                    <div class="card h-100">
                                        <img
                                        src="${image}"
                                        class="card-img-top"
                                        />
                                        <div class="card-body">
                                        <h5 class="card-title">${title}</h5>
                                        <p class="card-text">${desc}</p>
                                        <p>${star_repeat}</p>
                                        <p class="mycomment">${comment}</p>
                                        </div>
                                    </div>
                                </div>`;
              $("#cards-box").append(temp_html);
            });

 

미니프로젝트2 완성 모습

댓글