
* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.
* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.
4주차 강의 때 프로젝트 폴더에서는 database.db 파일만 생성하고 db폴더로 넘어갔었는데 5주차 강의 상에서는 프로젝트 폴더에 들어가니까 flask shell 터미널 명령어가 입력된 상태로 되어있는데 db폴더에서 작업을 한게 project 폴더에도 영향이 가나요? 이거 때문인지는 모르겠지만 터미널에서 python app.py입력 후 Music 탭으로 넘어가면 빌드 에러가 뜨네요

# motto.html 파일 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<style>
body {
background-image: url("https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/images/background.jpg");
background-position: center;
background-size: cover;
color: white;
}
/* .navbar {
display: flex;
justify-content: space-between;
align-items: center;
} */
.weather {
display: flex;
align-items: center;
margin-right: 30px;
}
.container {
display: flex;
flex-direction: column;
/* Flex 안의 아이템들을 세로 방향으로 배치합니다. */
justify-content: center;
/* 주축 방향으로 가운데 정렬합니다. */
align-items: center;
/* 교차축 방향으로 가운데 정렬합니다. */
height: 100vh;
text-align: center;
}
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
text-align: center;
font-weight: bold;
padding: 20px 0;
}
.greeting {
margin-bottom: 50px;
}
.motto {
margin-bottom: 100px;
}
.logo {
height: 32px;
margin-left: 30px;
}
@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
* {
font-family: 'Poppins', sans-serif;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
</head>
<body>
<!-- music의 navbar -->
<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 text-white" aria-current="page" href="{{ url_for('home')}}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="{{ url_for('music')}}">Music</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#">Album</a>
</li>
<li class="nav-item">
<a class="nav-link text-white">Movie</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="weather">
<img id="weather-icon">
<p id="weather-msg"></p>
</div>
</nav>
<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>
<div class="footer">
<p id="quoteAuthor"></p>
<p id="quoteContent"></p>
</div>
<script>
function displayCurrentTime() {
var currentTime = new Date();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();
var seconds = currentTime.getSeconds();
// AM 또는 PM 설정
var meridiem = hours >= 12 ? "PM" : "AM";
// 시간이 12를 넘어가면 12로 나눠서 표시
hours = hours > 12 ? hours - 12 : hours;
// 0을 붙여 한 자리 숫자를 두 자리로 만듦
hours = addLeadingZero(hours);
minutes = addLeadingZero(minutes);
seconds = addLeadingZero(seconds);
// 시간을 HTML 요소에 표시
var timeString = hours + ":" + minutes + ":" + seconds + " " + meridiem;
document.getElementById("current-time").innerHTML = timeString;
}
function addLeadingZero(number) {
return number < 10 ? "0" + number : number;
}
// 1초마다 시간을 업데이트
setInterval(displayCurrentTime, 1000);
let url = "https://api.quotable.io/random";
fetch(url).then(res => res.json()).then(data => {
console.log(data);
let author = data['author']
let content = data['content']
let authorMsg = `- ${author} -`
let contentMsg = `" ${content} "`
$('#quoteAuthor').text(authorMsg)
$('#quoteContent').text(contentMsg)
})
let weather_url = "http://spartacodingclub.shop/sparta_api/weather/seoul";
fetch(weather_url)
.then(res => res.json())
.then(data => {
// console.log(data);
let temp = data['temp']
let icon_url = data['icon']
let message = `${temp}ºC`
$('#weather-msg').text(message)
$('#weather-icon').attr('src', icon_url)
})
</script>
<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>
</html>
#music.html 파일 코드
<!Doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<style>
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css");
.background-banner {
background-image: linear-gradient(45deg,
rgb(51 43 43 / 75%),
rgb(20 19 20 / 61%)), url("https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/images/music_festival.jpg");
max-height: 100%;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
}
</style>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body data-bs-theme="dark">
<div class="background-banner">
<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 text-white" aria-current="page" href="{{ url_for('home')}}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="{{ url_for('music')}}">Music</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#">Album</a>
</li>
<li class="nav-item">
<a class="nav-link text-white">Movie</a>
</li>
</ul>
</div>
</div>
</nav>
</nav>
<div class="px-4 py-5 my-5 text-center">
<h1 class="display-5 fw-bold text-body-emphasis">멜로디 쉐어</h1>
<div class="col-lg-6 mx-auto">
<p class="lead mb-4">
<br>
노래를 들으면 생각나는 누군가가 있으신가요?
<br><br>
당신의 감성이 담긴 인생곡 플레이리스트
<br>
멜로디쉐어에서 소중한 사람과 함께 공유하세요.
</p>
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center">
<!-- Button trigger modal -->
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#exampleModal">
음악 추가
</button>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">최애 음악</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action ="{{ url_for('music_create')}}" method = "GET">
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">유저</label>
<input type="text" class="form-control" id="exampleInputEmail1"
aria-describedby="emailHelp" name = "username">
<div id="emailHelp" class="form-text">사용자(추천인)의 이름을 넣어주세요.</div>
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">노래 제목</label>
<input type="text" class="form-control" id="exampleInputPassword1" name = "title">
<div id="emailHelp" class="form-text">좋아하는 노래 제목을 넣어주세요.</div>
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">가수</label>
<input type="text" class="form-control" id="exampleInputPassword1" name = "artist">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">앨범 커버URL</label>
<input type="text" class="form-control" id="exampleInputPassword1" name = "image_url">
</div>
<button type="submit" class="btn btn-danger">Submit</button>
</form>
</div>
</div>
</div>
</div>
<div class="row row-cols-1 row-cols-md-4 g-4 mx-auto w-75 pb-5">
<div class="col">
<div class="card h-100">
<img src="https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/ive.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Love Dive</h5>
<p class="card-text">아이브(IVE)</p>
<p class="card-text">추천 by 최지웅</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<img src="https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/ive.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Love Dive</h5>
<p class="card-text">아이브(IVE)</p>
<p class="card-text">추천 by 최지웅</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<img src="https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/ive.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Love Dive</h5>
<p class="card-text">아이브(IVE)</p>
<p class="card-text">추천 by 최지웅</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<img src="https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/ive.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Love Dive</h5>
<p class="card-text">아이브(IVE)</p>
<p class="card-text">추천 by 최지웅</p>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<footer>
<div class="d-flex flex-column flex-sm-row justify-content-between py-4 my-4 border-top">
<p>© 2023 Company, Inc. All rights reserved.</p>
<ul class="list-unstyled d-flex">
<li class="ms-3"><a class="link-body-emphasis" href="https://www.youtube.com/@SpartaCodingClub"><i class="bi bi-youtube"></i></a></li>
<li class="ms-3"><a class="link-body-emphasis" href="https://www.instagram.com/spartacodingclub/"><i class="bi bi-instagram"></i></a></li>
<li class="ms-3"><a class="link-body-emphasis" href="https://spartacodingclub.kr/blog"><i class="bi bi-postcard"></i></a></li>
</ul>
</div>
</footer>
</div>
<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>
</html>
#app.py 파일 코드
# 필수 라이브러리
# '''
# 0. Flask : 웹서버를 시작할 수 있는 기능. app이라는 이름으로 플라스크를 시작한다
# 1. render_template : html파일을 가져와서 보여준다
# '''
from flask import Flask, render_template, request
app = Flask(__name__)
#DB 기본 코드
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)
class Song(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), nullable=False)
artist = db.Column(db.String(100), nullable=False)
title = db.Column(db.String(100), nullable=False)
image_url = db.Column(db.String(10000), nullable=False)
def __repr__(self):
return f'{self.username} {self.title} 추천 by {self.username}'
with app.app_context():
db.create_all()
@app.route("/")
def home():
name = '최지웅'
motto = "행복해서 웃는게 아니라 웃어서 행복합니다."
context = {
"name": name,
"motto": motto,
}
return render_template('motto.html', data=context)
@app.route("/music/")
def music():
return render_template('music.html')
@app.route("/iloveyou/<name>/")
def iloveyou(name):
motto = f"{name}야 난 너뿐이야!"
context = {
'name': name,
'motto': motto,
}
return render_template('motto.html', data=context)
@app.route("/music/crate/")
def music_creat():
#form에서 보낸 데이터 받아오기
username_receive = request.args.get("username")
title_receive = request.args.get("title")
artist_receive = request.args.get("artist")
image_receive = request.args.get("image_url")
# 데이터를 DB에 저장하기
song = Song(username = username_receive, title=title_receive, artist=artist_receive, image_url = image_receive)
db.session.add(song)
db.session.commit()
return render_template('music.html')
if __name__ == "__main__":
app.run(debug=True)
