2024. 2. 5. 22:25ㆍ카테고리 없음
강의 자료
4주차
02. [데일리모토] - 프로젝트 세팅
프로젝트 설정
신규 projects 디텍토리 생성 및 기존에 작성한 motto, music.html을 templates 디텍토리도 복사한다.
python venv 설정
터미널에서 다음 명령어로 venv 생성 후 인터프리터에서 필요한 python 버전 선택
python -m venv venv
프로젝트에서 다음 명령어로 venv 활성화
source venv/bin/activate
터미널에 (venv)가 출력된다.
이후 flask 패키지를 설치한다.
pip install flask
04. [데일리모토] - 라우팅 연습
주소에 따른 HTML 파일 렌더링
주소에 따라 html파일이 보여지도록 설정한다. app.py를 다음과 같이 편집한다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
return render_template("motto.html")
@app.route("/music/")
def music():
return render_template("music.html")
if __name__ == "__main__":
app.run(debug=True, port=8080)
localhost:8080에서는 다음과 같이 출력되며,
localhost:8080/music 에서는 다음과 같이 출력된다.
Python 서버에서 HTML 파일로 데이터 넘겨주기
python 변수에 따라 인사말이 바뀌도록 수정한다.
app.py을 다음과 같이 수정한다.
def home():
name = 'sparta'
return render_template("motto.html", data=name)
motto.html을 다음과 같이 수정한다.
<div class="container">
<div class="greeting">
<h1>Hello, {{ data.name }}</h1>
<h1 id="current-time"></h1>
</div>
<div class="motto">
<h3>My life's motto</h3>
<h2>{{data.motto}}</h2>
</div>
</div>
다음과 같이 이름과 모토가 출력된다.
05. [데일리모토] - URL 주소에서 데이터 가져오기
주소에 따라 메인 화면 인사말 바꾸기
코드를 다음과 같이 작성한다.
@app.route("/iloveyou/<name>/")
def iloveyou(name):
motto = f"{name}야 난 너뿐이야..."
context = {
"name": name,
"motto": motto
}
return render_template("motto.html", data=context)
route에 <>를 사용하면 URL 주소에 따라 <> 안에 내용을 변수처럼 쓸 수 있다. http://localhost:8080/iloveyou/silee 로 url을 접속하면 name에 silee가 출력된다.
06. [데일리모토] - 페이지 이동 기능 만들기
데일리모토 Navbar에 페이지 이동 기능을 구현한다.
Navbar에 메뉴 추가
Bootstrap CSS CDN 추가
head태그 하위에 링크를 추가
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
...
</head>
Bootstrap JavaScript CDN 추가
</body> 태그 위에 CDN을 추가한다.
<body>
...
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz"
crossorigin="anonymous"></script>
</body>
nav 태그 수정
다음과 같이 nav 태그를 수정한다.
<nav class="navbar border-bottom border-bottom-dark d-flex justify-content-space-between" data-bs-theme="dark">
<div class="ms-3">
<img src="https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/images/sparta-logo.svg"
alt="" />
</div>
<nav class="navbar navbar-expand-lg">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Music</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Album</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Movie</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="weather">
<img src="https://ssl.gstatic.com/onebox/weather/64/partly_cloudy.png" id="weather-icon">
<p id="weatherTemp">날씨 맑음, 20ºC</p>
</div>
</nav>
navbar에 페이지 이동 기능 구현하기
{{url_from('이동할 곳')}} 형식으로 수정한다. motto.html, music.html를 각각 다음과 같이 수정한다.
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('home') }}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('music') }}">Music</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Album</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Movie</a>
</li>
</ul>
</div>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('home') }}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('music') }}">Music</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Album</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Movie</a>
</li>
</ul>
</div>
위의 navbar에서 Home, Music에서 페이지 이동이 정상 동작한다.
07. Database(DB) 개괄
SQLite Editor VScode Extension을 설치한다.
database.db를 추가하면 화면에 다음과 같이 출력된다.
08. SQLite 시작하기
SQLAlchemy로 Database 연결 & 테이블 만들기
다음 명령어로 SQLAlchemy로 패키지를 설치한다.
pip install Flask-SQLAlchemy
다음코드로 SQLAlchemy를 초기화한다.
from flask import Flask
import os
from flask_sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, 'database.db')
db = SQLAlchemy(app)
이후 app.py에 Song 클래스를 추가 후 다음과 같이 구현한다.
class Song(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, nullable=False)
artist = db.Column(db.String, nullable=False)
title = db.Column(db.String, nullable=False)
image_url = db.Column(db.String, nullable=False)
def __repr__(self):
return f'{self.artist} {self.title} 추천 by {self.username}'
table을 생성은 다음과 같이 진행한다.
>>> from app import Song, app, db
>>> with app.app_context():
... db.create_all()
위와 같이 database.db에 song 테이블이 추가된다.
table을 drop하기위해서는 다음과 같이 진행한다.
>>> from app import Song, app, db
>>> with app.app_context():
... db.drop_all()
위와 같이 database.db에 table이 제거된다.
09. SQLAlchemy로 Database 조작하기
여러 데이터 넣기
from app import Song, db, app
song1 = Song(username="추천자", title="노래제목1",
artist="가수1", image_url="이미지 주소1")
song2 = Song(username="스파르타", title="노래제목2",
artist="가수2", image_url="이미지 주소2")
song3 = Song(username="스파르타", title="노래제목3",
artist="가수3", image_url="이미지 주소3")
with app.app_context():
db.session.add(song1)
db.session.add(song2)
db.session.add(song3)
db.session.commit()
database.db에 데이터가 추가된다.
모든 결과 값 조회
다음과 같이 함수를 호출할 경우 def __repr__(self) 함수에서 리턴하는 포맷으로 조회가 된다.
>>> from app import Song, app, db
>>> with app.app_context():
... Song.query.all()
...
[가수1 노래제목1 추천 by 추천자, 가수2 노래제목2 추천 by 스파르타, 가수3 노래제목3 추천 by 스파르타]
def __repr__(self):
return f'{self.artist} {self.title} 추천 by {self.username}'
특정 조건으로 데이터 가져오기
Song.query.filter_by(조건).all()을 사용하면 조건에 맞는 데이터를 전부 가져올 수 있다.
>>> with app.app_context():
... Song.query.filter_by(username='추천자').all()
...
[가수1 노래제목1 추천 by 추천자]
>>> with app.app_context():
... Song.query.filter_by(id=3).first()
...
가수3 노래제목3 추천 by 스파르타
>>> with app.app_context():
... Song.query.filter_by(title='노래제목1').first()
...
가수1 노래제목1 추천 by 추천자
데이터 수정하기
다음과 같이 query를 통해 저장된 record를 가져온 후 db.session.add 함수 및 db.session.commit 함수를 호출하여 수정을 진행한다.
from app import Song, db, app
with app.app_context():
print(Song.query.all())
song_data = Song.query.filter_by(id=3).first()
song_data.title = '노래제목수정'
db.session.add(song_data)
db.session.commit()
print(Song.query.all())
다음과 같이 변경된 값으로 출력된다.
데이터 삭제하기
데이터 수정과 동일하게 해당 query로 저장된 record를 가져온 후 db.session.delete 함수 및 db.session.commit 함수를 호출하여 삭제를 진행한다.
from app import Song, db, app
with app.app_context():
print(Song.query.all())
delete_data = Song.query.filter_by(id=3).first()
db.session.delete(delete_data)
db.session.commit()
print(Song.query.all())
다음과 같이 해당 값이 삭제된다.
10. Homework
멜론 Top 100차트에서 가수(artist), 노래 제목(title), 앨범 커버(image_url)을 스크래핑해서 카드 형태로 만든다.
http://127.0.0.1:5000/melon 에 접속하면 다음과 같이 출력된다.
신규 프로젝트 prac을 추가한후 app.py, templates/index.html을 생성한다.
이 후 venv 환경설정을 진행한 후 flask, bs4, requests 패키지를 다운 받는다.
prac % python -m venv venv
prac % source venv/bin/activate
(venv)prac % pip install flask bs4 requests
app.py에 다음과 같이 코드를 수정한다.
from flask import Flask, render_template
from bs4 import BeautifulSoup
import requests
app = Flask(__name__)
url = "https://www.melon.com/chart/"
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')
@app.route('/')
def home():
return render_template('index.html')
@app.route('/melon')
def melon():
data_list = []
trs = soup.select('.lst50') + soup.select('.lst100')
for tr in trs:
title = tr.select_one('.rank01 > span > a').text
artist = tr.select_one('.rank02 > a').text
image_url = tr.select_one('img')['src']
data_list.append({'title' : title, 'artist' : artist, 'image_url' : image_url})
context = data_list
return render_template('index.html', data=context)
if __name__ == '__main__':
app.run(debug=True, port=5000)
index.html의 Cards 부분을 다음과 같이 수정한다.
<div class="row row-cols-1 row-cols-md-4 g-4 mx-auto w-75 pb-5">
{% for melon in data %}
<div class="col">
<div class="card h-100">
<img src="{{melon.image_url}}"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{melon.title}}</h5>
<p class="card-text">{{melon.artist}}</p>
<p class="card-text">추천 by 최지웅</p>
</div>
</div>
</div>
{% endfor %}
</div>
다음과 같이 화면에 앨범 이미지, 타이틀, 아티스트이 출력된다.