기상 08:00
책상 옮기기 08:20
공부 시작 08:30
- 웹개발 플러스 강의 1주차 수강하기(우선 필요한 내용만)
- 검색 기능 구현
점심 13:10 - 13:45
개인 면담 13:50 - 14:00 달빛 테이블
👉 다음 면담 때에는 질문 더 정해서 가기
👉 알고리즘도 자바로 공부하는 거 추천 !!
공부 14:00
휴식15:30 - 15:40
검색 기능 구현 완료 16:12 잊지 못해 엉엉
- 못 구현한 기능 최대한 다 완성하기
투표 16:40 - 16:55
공부
휴식 20:00 - 20:30
로그인/회원가입 페이지 - render_template 으로 이동하는 거
메인 페이지 - 검색 기능
- OO 님 환영합니다 구현 - jinja2 문법 활용
- 더보기 기능 재구현
상세 페이지 - 댓글 기능 (DB저장, 보여주기)
- 수정/삭제 기능
공부
TIL 작성 00:30 - 01:10
하고 싶은 기능 - 뮤지컬 이미지에 커서 갖다댔을 때 테두리 부드러워지는 기능
👉 hover 기능 사용해서 border-radious 15px 정도 적용하면 될 것 같은데 어디에 적용해야 할 지 모르겠다
mongoDB 암호화 + Readme 파일 작성
오늘 구현하기로 한 기능들을 모두 구현했다. 수정 기능은 우선 뺐고 시간이 남으면 구현해보기로 했다!
어제는 진전이 없어서 힘든 하루였지만 오늘은 기능 구현에 배포까지 다 해봐서 두 다리 쭉 뻗고 잘 수 있을 것 같다.
내일은 CSS를 좀 다듬고 hover 기능도 좀 넣어서 좀 더 예쁘게 페이지를 꾸며보고 싶다!!
기능 구현을 다 하고 실행해볼 때 구현이 잘 되면 내가 짠 코드가 아니더라도 기분이 너무 좋고 뿌듯하다. 이 맛에 코딩한다 ㅎ,, 오늘 하루도 고생 많았다. 잘 자고 내일도 화이팅 해보자!!!!!!!
아 그 전에 오늘 배운 내용을 안 써서 좀 간략하게 써보자면,
먼저 더보기 버튼을 다시 만들었다. 원래 상세 페이지로 넘어갈 때 뮤지컬 정보를 갖고 가기 위해서 jinja2 문법으로 구현해놓았던 코드가 있었는데 그게 flask와 javascript로 구현해놓은 더보기 기능과 상충한 것이였는지 더보기 기능이 구현되지 않았었다. 그래서 해결한 방법은 jinja2 문법 대신 javascript로 다시 표현해서 더보기 기능과 같이 썼더니 두 기능 모두 잘 작동되었다.
//더보기 버튼 구현 + 상세페이지로 이동//
function list(page) {
$.ajax({
type: "GET",
url: "/list",
data: {'page': page},
success: function (response) {
let rows = response['musicals']
let last_page=response['last_page']
for (let i = 0; i < rows.length; i++) {
let image = rows[i]['image']
let title = rows[i]['title']
let temp_html = `<div class="col mb-5" style=" cursor: pointer;" onclick="location.href='/detail?${title}';">
<div class="card h-100">
<img class="card-img-top" src="${image}" alt="..."/>
<div class="card-body p-4">
<div class="text-center">
<h5 class="fw-bolder">${title}</h5>
</div>
</div>
</div>
</div>`
$('#musicals').append(temp_html)
}
$('#more-btn').empty();
page += 1;
let temp_html = `<a class="btn btn-secondary" onclick="list(${page})" >더보기</a></li>`
if (page != last_page) {
$('#more-btn').append(temp_html)
}
}
})}
그리고 검색 기능을 구현했다!!
##############메인페이지에 뮤지컬 정보 검색###############
@app.route('/index')
def home():
token_receive = request.cookies.get('mytoken')
search_title = request.args.get('search_title')
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
name = db.users.find_one({'username': payload['id']}) # 데이터베이스에서 email과 일치하는 name을 찾아서 name에 저장한다.
user = name["profile_name"]
if search_title is None:
# DB에서 뮤지컬 정보 모두 가져오기
all_musicals = list(db.musicals.find({}, {'_id': False}))
# 닉네임 & 뮤지컬 목록 반환하기
return render_template("index.html", all_musicals=all_musicals, name=user)
else:
search_musicals = list(db.musicals.find({"title": {"$regex": search_title}}, {'_id': False}))
return jsonify({'result':'success','search_musicals':search_musicals})
# return render_template("search_main.html", search_musicals=search_musicals, name=user)
except jwt.ExpiredSignatureError:
return redirect(url_for("login", msg="로그인 시간이 만료되었습니다."))
except jwt.exceptions.DecodeError:
return redirect(url_for("login", msg="로그인 정보가 존재하지 않습니다."))
search_musicals = list(db.musicals.find({"title": {"$regex": search_title}}, {'_id': False}))
{"$regex": ... } 이 함수를 사용하면 ... 에 들어가는 것과 일치하는 모든 값을 찾아준다고 한다.
그래서 제목과 일치하는 뮤지컬들을 보여주기 위한 우리 검색 기능에 이 함수를 사용했다.
다른 기수 분들이 하신 내용을 참고해서 수정해봤는데도 감이 안잡혔는데, 저 search_musicals를 print 해보고나서 console 창에 list로 찍히는 걸 보고 바로 ajax 코드까지 짜서 방법이 머리 속으로 그려지니 생각보다 금방 구현할 수 있었다. 기능을 구현하고 난 다음에 느낀 희열은 정말 잊을 수 없다.
//검색 기능 구현//
function find() {
let search_title = $('#find_text').val()
if (search_title == '') {
alert('검색할 제목을 입력해주세요.')
return;
} $('#musicals').empty();
event.preventDefault()
$.ajax({
type: "GET",
url: "/index",
data: {"search_title": search_title},
success: function (response) {
let rows = response['search_musicals']
for (let i=0; i<rows.length; i ++) {
let image = rows[i]['image']
let title = rows[i]['title']
let temp_html = `<div class="col mb-5" style=" cursor: pointer;" onclick="location.href='/detail?${title}';">
<div class="card h-100">
<img class="card-img-top" src="${image}" alt="..."/>
<div class="card-body p-4">
<div class="text-center">
<h5 class="fw-bolder">${title}</h5>
</div>
</div>
</div>
</div>`
$('#musicals').append(temp_html);
const moreBtn =document.querySelector('#more-btn');
moreBtn.style.display="none"
}
}
})
}
사실 다른 기수 분들이 짜신 코드처럼 멋있고 간결하진 않지만 기능을 구현해냈다는 것에 큰 보람과 성취감을 느낀다. 다음으로 댓글 삭제하는 기능을 함께 풀어봤다. 말처럼 쉽지 않았다.
우선 댓글의 고유한 값이 필요했고, 그러기 위해서는 각 댓글을 저장할 때 num 값을 주어야 했다.
다음으로 붙는 댓글에 대해서는 list의 길이에 1씩 더해준 값을 번호로 지정해 주었다. 지정한 그 num 값을 db에서 찾은 다음 ajax에 받아와서 삭제 버튼 옆에 delete 함수로 붙이고 그에 해당하는 댓글을 삭제할 수 있었다.
## 디테일 페이지 댓글 저장하기 (쿠키 id값도 빼와서 해당 유저 정보에 데이터 db저장)
@app.route('/detailc', methods=["POST"])
def detail_comment():
token_receive = request.cookies.get('mytoken')
comment_receive = request.form['comment_give']
star_receive = request.form['star_give']
title_receive = request.form['title_give']
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
name = db.users.find_one({'username': payload['id']})
user = name["profile_name"]
comment_list = list(db.commentSave.find({}, {'_id': False}))
count = len(comment_list) + 1
doc = {
'name': user,
'comment': comment_receive,
'star': star_receive,
'title': title_receive,
'num': count
}
db.commentSave.insert_one(doc)
return jsonify({'msg': '입력완료!'})
except jwt.ExpiredSignatureError:
return redirect(url_for("login", msg="로그인 시간이 만료되었습니다."))
except jwt.exceptions.DecodeError:
return redirect(url_for("login", msg="로그인 정보가 존재하지 않습니다."))
##디테일 페이지 댓글 삭제하기
@app.route('/detail_delete', methods=["POST"])
def del_comment():
token_receive = request.cookies.get('mytoken')
num_receive = request.form['num_give']
names = list(db.commentSave.find({'num': int(num_receive)}, {'_id': False}))
nam = names[0]
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
name = db.users.find_one({'username': payload['id']},{'_id':False})
if nam['name'] == name['profile_name']:
db.commentSave.delete_one({'num':int(num_receive)})
return jsonify({'msg': '삭제완료!'})
else:
return jsonify({'msg': '다른사람이 작성한 글입니다. 삭제할 수 없습니다.'})
except jwt.ExpiredSignatureError:
return redirect(url_for("login", msg="로그인 시간이 만료되었습니다."))
except jwt.exceptions.DecodeError:
return redirect(url_for("login", msg="로그인 정보가 존재하지 않습니다."))
그리고 내가 작성한 글만 삭제할 수 있도록 댓글을 달 때 입력한 닉네임과 가입을 했을 때 저장한 닉네임이 같은 지를 확인해서
(삭제 버튼을 눌렀을 때의 사용자의 닉네임값과 댓글을 단 닉네임 값을 비교하면 되는 거 아닌가??) 무튼
사실 이 기능은 완전히 이해하진 못했다. 그저 따라해보기 바쁜,, ㅋㅋ
아 그리고 ReadMe 파일 작성하는 법도 공부해서 나중에 작성해봐야지~!~!
+ 다음 면접 때에는 질문할 거 왕창 싸들고 가자 ~~ (공부 많이하고 이것저것 많이 찾아봐!!!)
알고리즘 공부도 자바로 하면 좋대!!
'스파르타코딩클럽 > 항해99' 카테고리의 다른 글
항해99 6기 DAY 6 TIL _ 22.03.12 (0) | 2022.03.13 |
---|---|
📅 항해99 B반 10조의 일일 알고리즘 스터디 사이클 📅 (0) | 2022.03.11 |
항해99 6기 DAY 4 TIL _ 22.03.10 (0) | 2022.03.11 |
항해99 6기 DAY 2 TIL _ 22.03.08 (0) | 2022.03.09 |
항해99 6기 DAY 1 TIL _ 22.03.07 (0) | 2022.03.07 |