수행 과제: 팀 소개 페이지
수행 기간: 23.05.15~23.05.19
시나리오
1. 사용자는 방명록을 수정/삭제하기 위해, 작성 시 등록한 기존의 비밀번호가 입력되어야 한다.
2. 수정 버튼 클릭 시, objectId 값을 key 값으로 가져와 수정할 방명록을 찾고, 입력한 비밀번호와 db에 저장된 비밀번호가 일치하는지 확인한다.
3-1. 비밀번호가 맞을 시, 텍스트 창을 수정가능하도록 변경한다.
3-2. 비밀번호가 틀릴 시, 비밀번호가 틀렸다는 메시지를 호출한다.
4. 수정할 텍스트를 입력 후 완료버튼 클릭 시, 수정된 방명록 글을 가져와 update한다.
(삭제 기능은 1,2,3번 로직을 동일하게 채용)
app.py
#방명록 수정하기
@app.route('/guestbook/3',methods=["POST","PUT"])
def guestbook_update():
if request.method == "POST": #수정할 방명록을 페이지에서 가져오기
objectId_receive = request.form['objectId_give'] #db 키(_id)값
targetpassword_receive = request.form['targetpassword_give']
target = db.guestbook.find_one({'_id':ObjectId(objectId_receive)}) #댓글 테이블에 (_id)값을 가진 아이디와 댓글이 있는지 확인
if target['password'] != targetpassword_receive: #입력한 비밀번호가 다를 때
return jsonify({'result':'fail', 'msg': '비밀번호가 틀립니다.'})
else: # 입력한 비밀번호가 맞을 때
return jsonify({'result':'success', 'msg': '수정할 내용을 작성하세요.'})
#요청메서드가 PUT인 경우 : 변경 반영
if request.method == "PUT":
objectId_receive = request.form['objectId_give']
targetpassword_receive = request.form['targetpassword_give']
comment_receive = request.form['updatecomment_give'] #새로 작성한 comment 불러오기
target = db.guestbook.find_one({'_id':ObjectId(objectId_receive)})
if target['password'] != targetpassword_receive: #비밀번호 한번 더 검증
return jsonify({'result':'fail', 'msg': '비밀번호가 틀립니다.'})
else:
# DB에 수정
db.guestbook.update_one(target,{'$set':{'comment':comment_receive}})
return jsonify({'result' : 'success', 'msg' : '수정이 완료되었습니다'})
js
function editbutton_clicked(button) {
// 클릭한 버튼의 id 가져오기위해 button을 인자값으로 받음
//button.value : <button>태그의 value($commentIdx) ex)방명록의 번호(1, 2, 3,...)
let objectId = button.getAttribute('data-id')
let targetpassword = $('#editpassword-' + button.value).val(); //입력한 pw
console.log(objectId)
let formData = new FormData();
formData.append("objectId_give", objectId);
formData.append("targetpassword_give", targetpassword);
fetch('/guestbook/3', { method: "POST", body: formData, }).then((response) => response.json()).then((data) => {
// 해당 버튼에 대한 처리
if (data["result"] == "success") {
var buttonId = $(this).attr('id');
$('#edit-button-' + button.value).hide();
$('#done-button-' + button.value).show();
$('#editcomment-' + button.value).addClass('form-control');
$('#editcomment-' + button.value).removeClass('form-control-plaintext');
$('#editcomment-' + button.value).prop('disabled', false);
}
else if (data["result"] == "fail") {
alert(data["msg"]);
}
});
}
function donebutton_clicked(button) {
let objectId = button.getAttribute('data-id')
let updatecomment = $('#editcomment-' + button.value).val()
let targetpassword = $('#editpassword-' + button.value).val();
let formData = new FormData();
formData.append("objectId_give", objectId);
formData.append("updatecomment_give", updatecomment)
formData.append("targetpassword_give", targetpassword);
fetch('/guestbook/3', { method: "PUT", body: formData, }).then((response) => response.json()).then((data) => {
// 해당 버튼에 대한 처리
if (data["result"] == "success") {
alert(data["msg"]);
window.location.reload();
}
else if (data["result"] == "fail") {
alert(data["msg"]);
}
});
}
방명록을 불러올 때 가져온 data-id(mongoDB의 id값)을 토대로, mongoDB에서 수정할 댓글을 확인한다.
방명록 수정/삭제대상 식별을 위해 사용한 ObjectId
db.(테이블명).find_one({검색조건}, {'id':False})로 값을 얻어와 html에 전달할 때에는 정상적으로 데이터를 불러왔지만, {'_id':True}로 했을 때는 html에서 방명록 정보를 아무것도 불러오지 못하는 문제가 있었다.
원인 : mongoDb의 '_id' 필드가 ObjectId(BSON형식)으로 되어 있기 때문에 HTML로 직접 전달할 수 없었다.
Try1: ObjectId를 통해 timestamp(생성시간)값을 얻는 방법이 있단것을 알게되어, html로 보낼때는 시간정보로 보내주어 댓글작성시간으로 활용하고, 이를 다시 서버에 돌려줄 때는 objectid로 변환하여 키값으로 활용하려는 일석이조의 생각을 품었지만, timestamp변환과정에서 objectid값이 손실되어 온전한 값으로 복원이 불가능했다.
Try2(해결) : objectId 내용을 string(문자열)로 변경하여 html에 전달하는 것에 성공했다. 이를 다시 서버로 보낼 때는 ObjectId라이브러리를 사용하여 다시 변환을 해주는 식으로 이를 해결했다.
알게된 점
mongoDB의 objectId구성
64661f0d/81504741c0/f9b58b
첫 4byte(1~8문자)는 timestamp값을 의미 (생성시간 값을 얻는 부분)
다음 5byte(9~18문자)는 랜덤 생성
다음 3byte(19~24문자)는 증가하는 count, 최초값은 랜덤생성