2024. 2. 2. 16:08ㆍ스파르타_부트캠프/웹개발
강의 자료
3주차
13. Flask로 로또 추천 사이트 만들기 2
로또 당첨 기능 구현하기
두개의 리스트 중 일치하는 숫자의 개수를 반환하는 함수를 구현한다.
def count_common_elements(list1, list2):
common = set(list1) & set(list2)
return len(common)
test_app.py의 단위 테스트에서 검증한다.
class Test(unittest.TestCase):
def test_count_common_elements(self):
self.assertEqual(0, count_common_elements([1, 2, 3], [4, 5, 6]))
self.assertEqual(1, count_common_elements([1, 2], [1, 3]))
self.assertEqual(3, count_common_elements([1, 2, 3], [1, 2, 3]))
정상 구현된 것을 확인하였다. 이제 lotto와 random_lotto의 일치 개수를 계산하여 context에 key, value로 설정 후 전달한다.
common_count = count_common_elements(lotto, lotto_numbers)
context = {
"name": name,
"lotto": lotto,
"random_lotto": lotto_numbers,
"common_count": common_count
}
index.html의 body 태그에 다음과 같이 값을 추가한다.
<body>
<h1>안녕, {{data.name}}</h1>
<h2>로또 번호:, {{data.lotto}}</h2>
<h3>랜덤 로또 번호:, {{data.random_lotto}}</h3>
{% if data.common_count == 6 %}
<h2>{{ data.common_count }}개 맞았습니다! 로또 1등입니다.</h2>
{% elif data.common_count == 5 %}
<h2>{{ data.common_count }}개 맞았습니다! 로또 2등입니다.</h2>
{% elif data.common_count == 4 %}
<h2>{{ data.common_count }}개 맞았습니다! 로또 3등입니다.</h2>
{% elif data.common_count == 3 %}
<h2>{{ data.common_count }}개 맞았습니다! 로또 4등입니다.</h2>
{% else %}
<h2>{{ data.common_count }}개 맞았습니다! 탈락입니다...😥😥</h2>
{% endif %}
</body>
다음과 같이 결과가 출력된다.
CSS추가하여 완성하기
html의 style에 다음을 추가한다.
<style>
.ball {
display: inline-block;
width: 30px;
height: 30px;
border-radius: 50%;
background-color: #FFD700;
color: #FFFFFF;
text-align: center;
line-height: 30px;
margin-right: 5px;
}
.randomball {
display: inline-block;
width: 30px;
height: 30px;
border-radius: 50%;
background-color: red;
color: #FFFFFF;
text-align: center;
line-height: 30px;
margin-right: 5px;
}
</style>
이후 index.html에 다음과 같이 코드를 수정한다.
<h1>로또 번호</h1>
{% for num in data.lotto %}
<div class="ball">{{ num|e }}</div>
{% endfor %}
<h1>랜덤 로또 번호</h1>
{% for num in data.random_lotto %}
<div class="randomball">{{ num|e }}</div>
{% endfor %}
다음과 같이 화면에 출력된다.
Flask 이미지 삽입하기
다음 링크에서 이미지를 다운 받은 후 프로젝트에서 static/image 폴더 생성 후 해당 폴더에 저장한다.
https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/webjong/coinman.png
html 반영을 위해 index.html 에 다음 코드를 추가한다.
.coinman {
height: 100px;
}
<img class="coinman" src="{{ url_for('static', filename='image/coinman.png') }}" alt="">
다음과 같이 화면에 출력되는 것을 확인할 수 있다.
14. 영화 검색 사이트 만들기
movie 페이지 보여주기
/movie 경로로 접속할 시 movie.html을 보여준다.
app.py에 다음 코드를 추가한다.
@app.route('/movie')
def movie():
return render_template('movie.html')
movie.html에 다음 코드를 추가한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>영화 검색</h1>
</body>
</html>
127.0.0.1:5001/movie에 다음과 같이 화면이 추가되었다.
영화 검색 기능 만들기
form 생성
영화 검색을 위한 html form을 생성한다. movie.html의 body 태그에 다음값을 추가한다.
<form action="{{ url_for('movie') }}">
<input type="text" name="query">
<button type="submit">검색</button>
</form>
app.py의 movie 항목에 다음 코드를 추가한다.
@app.route('/movie')
def movie():
print(flask.request.args.get('query'))
return flask.render_template('movie.html')
검색 클릭시 다음과 같이 콘솔에 출력된다.
검색 기능 구현
영화진흥원 API URL 끝에 &movieNm=기생충 을 추가한 후 주소창에 입력하면 다음과 같은 포맷으로 json을 반환한다.
http://kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.json?key=f5eef3421c602c6cb7ea224104795888&movieNm=기생충
{
"movieListResult": {
"totCnt": 4,
"source": "영화진흥위원회",
"movieList": [
{
"movieCd": "20236433",
"movieNm": "사랑하는 기생충",
"movieNmEn": "Parasite in Love",
"prdtYear": "2021",
"openDt": "20240116",
"typeNm": "장편",
"prdtStatNm": "개봉",
"nationAlt": "일본",
"genreAlt": "드라마",
"repNationNm": "일본",
"repGenreNm": "드라마",
"directors": [
{
"peopleNm": "카키모토 켄사쿠"
}
],
"companys": []
},
...
]
}
}
이를 통해 movieNm에 입력값 query를 추가하여 url을 생성하여 결과를 가져온다.
app.py에 다음 코드를 추가한다.
@app.route('/movie')
def movie():
query = flask.request.args.get('query')
URL = (f"http://kobis.or.kr/kobisopenapi/webservice/rest/movie/"
f"searchMovieList.json?key=f5eef3421c602c6cb7ea224104795888&movieNm={query}")
res = requests.get(URL)
rjson = res.json()
movie_list = rjson["movieListResult"]["movieList"]
return flask.render_template('movie.html', data=movie_list)
movie.html에 데이터를 출력하도록 기능을 구현한다.
<body>
<h1>영화 검색</h1>
<form action="{{ url_for('movie') }}">
<input type="text" name="query">
<button type="submit">검색</button>
</form>
{% for movie in data %}
<!-- <p>{{ movie }}</p> -->
<p>영화 제목: {{ movie.movieNm }}</p>
<p>타입: {{ movie.typeNm }}</p>
{% if movie.directors %}
<p>감독: {{ movie.directors[0].get('peopleNm') }}</p>
{% endif %}
<hr>
{% endfor %}
</body>
검색 시 다음과 같이 결과가 출력된다.
15. Homework
검색 날짜에 따라(YYYYMMDD 포맷) 1~10등까지 영화 등수, 영화명, 영화 개봉일, 누적 관객 수를 출력한다.
/answer경로에 해당 페이지를 추가한다.
검색어가 없는 경우 20230601을 디폴트로 한다.
영화 박스오피스 API 주소
http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.json?key=f5eef3421c602c6cb7ea224104795888&targetDt=20230601
해당 URL에 접근시 다음과 같은 json 반환
{
"boxOfficeResult": {
"boxofficeType": "주말 박스오피스",
"showRange": "20230602~20230604",
"yearWeekTime": "202322",
"weeklyBoxOfficeList": [
{
"rnum": "1",
"rank": "1",
"rankInten": "1",
"rankOldAndNew": "OLD",
"movieCd": "20226411",
"movieNm": "범죄도시3",
"openDt": "2023-05-31",
"salesAmt": "28690098096",
"salesShare": "87.6",
"salesInten": "25444261553",
"salesChange": "783.9",
"salesAcc": "44614489126",
"audiCnt": "2817135",
"audiInten": "2511765",
"audiChange": "822.5",
"audiAcc": "4512223",
"scrnCnt": "2582",
"showCnt": "42571"
},
...
]
}
}
app.py 코드
@app.route('/answer')
def answer():
query = flask.request.args.get('query')
if len(query) == 0:
query = '20230611'
URL = (f"http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/"
f"searchWeeklyBoxOfficeList.json?key=f5eef3421c602c6cb7ea224104795888&targetDt={query}")
res = requests.get(URL)
rjson = res.json()
movie_list = rjson["boxOfficeResult"]["weeklyBoxOfficeList"]
return flask.render_template('answer.html', data=movie_list)
answer.html 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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">
</head>
<body>
<h1>박스오피스 검색</h1>
<p>20230501 형식으로 검색하세요.</p>
<form action="{{ url_for('answer') }}">
<input type="text" name="query">
<button type="submit">검색</button>
</form>
<table class="table">
<thead>
<tr>
<th scope="col">랭킹</th>
<th scope="col">영화명</th>
<th scope="col">영화개봉일</th>
<th scope="col">누적관객수</th>
</tr>
</thead>
<tbody>
{% for movie in data %}
<tr>
<th>{{ movie.rank }}</th>
<td>{{ movie.movieNm }}</td>
<td>{{ movie.openDt }}</td>
<td>{{ movie.audiAcc }}명</td>
</tr>
{% endfor %}
</tbody>
</table>
<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>
다음과 같이 출력된다.
'스파르타_부트캠프 > 웹개발' 카테고리의 다른 글
ChatGPT 웹개발 진행노트 - 5일차 (0) | 2024.01.25 |
---|---|
ChatGPT 웹개발 진행노트 - 4일차 (0) | 2024.01.23 |
ChatGPT 웹개발 진행노트 - 3일차 (0) | 2024.01.22 |
ChatGPT 웹개발 진행노트 - 2일차 (0) | 2024.01.20 |
ChatGPT 웹개발 진행노트 - 1일차 (0) | 2024.01.19 |