1. 배운 것
Flask 프레임워크를 활용해서 API 만들기,
화성땅 공동구매, 스파르타피디아 미니프로젝트 두 개로 API 만들고 클라이언트에 연결하는 연습하기!
2. Flask 시작하기
▼ 는 요기 포스팅 ▼
https://chaeyami.tistory.com/14
[내일배움캠프] 스파르타코딩클럽 웹개발종합반 4주차(1) - Flask 시작하기
Flask 시작하기 Flask 프레임워크를 이용해서 서버를 만들고 데이터를 주고받을 거다. 역시나 가상환경에 라이브러리 설치하자 pip install flask Flask 시작 코드 # ./venv/app.py from flask import Flask app = Flask(
chaeyami.tistory.com
3. Flask 연습하기 - 미니프로젝트
화성땅 공동구매
▼ 는 요기 포스팅 ▼
https://chaeyami.tistory.com/16
[내일배움단] 스파르타코딩클럽 웹개발 종합반 4주차(2) TIL - 미니프로젝트 : 화성땅 공동구매
준비하기 **익숙해져야 할 패턴** 더보기 1. 파이썬 가상환경 활성화 : app.py 만들고 터미널에 python -m venv venv 2. HTML 준비 : ./templates 폴더 생성 > ./templats/index.html 파일 생성 3. 가상환경에 flask 프레
chaeyami.tistory.com
첫번째 연습! 4주차에 한 번 더, 5주차에 두 번 더 연습 총 4번이나 연습할 예정이다. 다 끝나고 나면 못 할 수가 없겠는데...?
스파르타피디아
이전에 프론트앤드 강의하면서 만들었던 스파르타피디아를 클라이언트-서버가 통신하는 페이지로 다시 만들어보기!
▼ 는 요기 포스팅 ▼
https://chaeyami.tistory.com/17
[내일배움단] 스파르타코딩클럽 웹개발 종합반 4주차 TIL 3 - 미니프로젝트 : 스파르타피디아
이전에 프론트엔드 강의하면서 만들었던 스파르타피디아를 클라이언트-서버가 통신하는 페이지로 다시 만들어보기! 서버-클라이언트 통신하는 GET, POST는 이전 화성땅 공동구매랑 동일한 방법
chaeyami.tistory.com
4주차 숙제
4주차 숙제는
완성한 스파르타피디아 페이지에 별점을 입력받고 가져오기!
url, comment 처럼 별점도 똑같이 만들어보라는 것이당
app.py
에서
별점을 가져오는 변수를 star_receive
라고 주고, 마찬가지로 클라이언트에서 star_give
라고 받아오도록 작성.
movie_post
함수 내에 받아오는 변수를 주고, 데이터를 DB에 저장하는 doc
부분도 추가
# app.py
#================= POST =================
@app.route("/movie", methods=["POST"])
def movie_post():
url_receive = request.form['url_give'] # url 받기
comment_receive = request.form['comment_give'] #comment 받기
star_receive = request.form['star_give'] #별점받기 ==========추가된부분==========
# ==== crolling ====
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']
# 모든 데이터 DB에 저장
doc = {
'image':ogimage,
'title':ogtitle,
'desc':ogdesc,
'comment':comment_receive,
'star' : star_receive # 별점 입력받는 부분 ==========추가된부분==========
}
db.movies.insert_one(doc)
return jsonify({'msg':'저장 완료!'})
이제 클라이언트에 실제로 star_give
값을 받도록 수정하면 된다. 이 값은 숫자로 받을 거다.
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>
<option value="2">⭐⭐</option>
<option value="3">⭐⭐⭐</option>
<option value="4">⭐⭐⭐⭐</option>
<option value="5">⭐⭐⭐⭐⭐</option>
</select>
</div>
이러한 형태이기 때문에, id="star"
를 골라 그 value
를 가져온다.
// index.html
// function posting() 내부
let star = $('#star').val()
formData.append("star_give",star);
스크립트 내부에 이 두 줄을 추가한다. 값을 가져오고 서버에 보낼 formData
까지
저장하고 새로 작성해보면,
이전과 달리 별점까지 잘 나오는 것을 확인할 수 있다!
전체 코드
# app.py
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
import requests
from bs4 import BeautifulSoup
# DB연결
from pymongo import MongoClient
client = MongoClient('mongodb+srv://sparta:test@cluster0.q4j284y.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta
# index.html 가져오기
@app.route('/')
def home():
return render_template('index.html')
#================= POST =================
@app.route("/movie", methods=["POST"])
def movie_post():
url_receive = request.form['url_give'] # url 받기
comment_receive = request.form['comment_give'] #comment 받기
star_receive = request.form['star_give'] #별점받기
# ==== crolling ====
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']
# 모든 데이터 DB에 저장
doc = {
'image':ogimage,
'title':ogtitle,
'desc':ogdesc,
'comment':comment_receive,
'star' : star_receive
}
db.movies.insert_one(doc)
return jsonify({'msg':'저장 완료!'})
#================= GET =================
@app.route("/movie", methods=["GET"])
def movie_get():
all_movies = list(db.movies.find({},{'_id':False})) # DB에서 파일 전부 가져오기
return jsonify({'result':all_movies})
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)
<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<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>
<link href="https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap" rel="stylesheet">
<style>
* {
font-family: 'Gowun Dodum', sans-serif;
}
.mytitle {
width: 100%;
height: 250px;
background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('https://movie-phinf.pstatic.net/20210715_95/1626338192428gTnJl_JPEG/movie_image.jpg');
background-position: center;
background-size: cover;
color: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.mytitle>button {
width: 200px;
height: 50px;
background-color: transparent;
color: white;
border-radius: 50px;
border: 1px solid white;
margin-top: 10px;
}
.mytitle>button:hover {
border: 2px solid white;
}
.mycomment {
color: gray;
}
.mycards {
margin: 20px auto 0px auto;
width: 95%;
max-width: 1200px;
}
.mypost {
width: 95%;
max-width: 500px;
margin: 20px auto 0px auto;
padding: 20px;
box-shadow: 0px 0px 3px 0px gray;
display: none;
}
.mybtns {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-top: 20px;
}
.mybtns>button {
margin-right: 10px;
}
</style>
<script>
$(document).ready(function () {
listing();
});
function listing() { //페이지 로딩이 완료되면
fetch('/movie').then((res) => res.json()).then((data) => { // /movie에 요청
let rows = data['result'] // app.py > return jsonify({'result':all_movies})
// 역시나 list를 하나씩 꺼내주기
$('#cards-box').empty()
rows.forEach((a) => {
let title = a['title']
let image = a['image']
let desc = a['desc']
let comment = a['comment']
let star = a['star']
let star_repeat = '⭐'.repeat(star)
// html에 담아주기
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)
})
})
}
function posting() { // 기록하기 botton => onclick="posting()"
// 데이터 가져오기
let url = $('#url').val() // input id="url"
let comment = $('#comment').val() // textarea id="comment"
let star = $('#star').val()
let formData = new FormData();
// 데이터 formData에 넣어서 보내버리기
formData.append("url_give", url);
formData.append("comment_give", comment);
formData.append("star_give",star);
fetch('/movie', { method: "POST", body: formData }).then((res) => res.json()).then((data) => {
alert(data['msg'])
window.location.reload() // refresh
})
}
function open_box() {
$('#post-box').show()
}
function close_box() {
$('#post-box').hide()
}
</script>
</head>
<body>
<div class="mytitle">
<h1>내 생애 최고의 영화들</h1>
<button onclick="open_box()">영화 기록하기</button>
</div>
<div class="mypost" id="post-box">
<div class="form-floating mb-3">
<input id="url" type="email" class="form-control" placeholder="name@example.com">
<label>영화URL</label>
</div>
<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>
<option value="2">⭐⭐</option>
<option value="3">⭐⭐⭐</option>
<option value="4">⭐⭐⭐⭐</option>
<option value="5">⭐⭐⭐⭐⭐</option>
</select>
</div>
<div class="form-floating">
<textarea id="comment" class="form-control" placeholder="Leave a comment here"></textarea>
<label for="floatingTextarea2">코멘트</label>
</div>
<div class="mybtns">
<button onclick="posting()" type="button" class="btn btn-dark">기록하기</button>
<button onclick="close_box()" type="button" class="btn btn-outline-dark">닫기</button>
</div>
</div>
<div class="mycards">
<div class="row row-cols-1 row-cols-md-4 g-4" id="cards-box">
<div class="col">
<div class="card h-100">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top">
<div class="card-body">
<h5 class="card-title">영화 제목이 들어갑니다</h5>
<p class="card-text">여기에 영화에 대한 설명이 들어갑니다.</p>
<p>⭐⭐⭐</p>
<p class="mycomment">나의 한줄 평을 씁니다</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top">
<div class="card-body">
<h5 class="card-title">영화 제목이 들어갑니다</h5>
<p class="card-text">여기에 영화에 대한 설명이 들어갑니다.</p>
<p>⭐⭐⭐</p>
<p class="mycomment">나의 한줄 평을 씁니다</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top">
<div class="card-body">
<h5 class="card-title">영화 제목이 들어갑니다</h5>
<p class="card-text">여기에 영화에 대한 설명이 들어갑니다.</p>
<p>⭐⭐⭐</p>
<p class="mycomment">나의 한줄 평을 씁니다</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<img src="https://movie-phinf.pstatic.net/20210728_221/1627440327667GyoYj_JPEG/movie_image.jpg"
class="card-img-top">
<div class="card-body">
<h5 class="card-title">영화 제목이 들어갑니다</h5>
<p class="card-text">여기에 영화에 대한 설명이 들어갑니다.</p>
<p>⭐⭐⭐</p>
<p class="mycomment">나의 한줄 평을 씁니다</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
이제 5주차만 끝나면 완강이다. 진도가 끝나가는 게 아쉬운 강의라니...
뭐 어차피 내일배움캠프에서 열심히 열심히 할 거니까 괜찮다!
GitHub 댓글