✅ POST
☑️ FE: JS:
📌 function handleSubmit
when clicked, call function handleSubmit
submit automatically reloads page, so prevent reload default
1
2
3
4
| function handleSubmit(event) {
//submit reloads page automatically, so prevent reload default
event.preventDefault();
}
|
client input.value has to be let
, as it will be changed
1
2
| const clientInput = document.querySelector(".memo_input");
let clientInputValue = clientInput.value;
|
and clear the input tag
1
2
| createMemo(clientInputValue);
clientInputValue = "";
|
📌 function createMemo
POST method
1
2
3
4
| body: JSON.stringify({
id: new Date().getTime(),
content: value;
}),
|
값을 ``로 감싸줘야 한다.
그 이유는 통신을 할 때는 문자열로만 할 수 있기 떄문이다.
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| async function createMemo(value) {
//post on server
const res = await fetch("/memos", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: new Date().getTime(),
content: value
})
});
const jsonRes = await res.json();
}
|
☑️ BE: PYTHON
class 미리 설정해 두어야 한다.
아까 JS에서도 이렇게 정의해주기로 했음.
1
2
3
| class Memo(BaseModel):
id: str
content: str
|
array를 하나 만들어 안에 memo넣을 것임
1
2
3
4
5
6
| memos= []
@app.post("/memos")
def create_memo(memo):
memos.append(memo)
return "memo created successfully"
|
📌 def create_memo
@app.post(“/memos”)
memos라는 경로로 받을 건데, memo로 받을 거야.
CODE
1
2
3
4
5
6
7
8
9
10
| class Memo(BaseModel):
id: str
content: str
memos= []
@app.post("/memos")
def create_memo(memo:Memo):
memos.append(memo)
return "memo created successfully"
|
✅ GET
☑️ FE: JS:
📌 function readMemo
디폴트로 가는 건 GET요청 이 함수는 언제 실행되어야 할까? (1) 페이지가 처음에 로딩되었을 떄 (2) 새로운 메모를 추가했을 때 createMemo
CODE
1
2
3
4
| async function readMemo() {
const res = await fetch("/memos");
const jsonRes = await res.json();
}
|
☑️ BE: PYTHON
CODE
1
2
3
| @app.get("/memos")
def read_memo():
return memos
|
☑️ FE: JS:
forEach
BE에서 memos를 array로 내려주면 FE createMemo 함수에서는 그것을 받아 배열 안에서 빙글빙글 돌면서 하나하나 받아 화면에 보여줘야 한다. 그러기 위해 displayMemo 함수에 배열에서 받은 것을 전달함. 이 코드는 createMemo 함수안에서 일어나야 함을 주의!
1
2
3
4
5
6
| async function readMemo() {
const res = await fetch("/memos");
const jsonRes = await res.json();
jsonRes.forEach(displayMemo);
}
|
📌 function displayMemo
먼저 보여줄 li, ul을 만들어야 함
read한 memo를 화면에 보여주기
먼저 보여줄 li, ul을 만들어야 함.
1
2
3
| const ul = document.querySelector(".memo_ul");
const li = document.createElement("li");
ul.appendChild(li);
|
그리고 li의 innerText를 memo.content로 정의
1
| li.innerText = `id:${memo.id} content:${memo.content}`;
|
CODE
이 때 memo를 parameter로 받아와야 함 주의!
1
2
3
4
5
6
7
| function displayMemo(memo) {
const ul = document.querySelector(".memo_ul");
const li = document.createElement("li");
ul.appendChild(li);
li.innerText = `id:${memo.id} content:${memo.content}`;
}
|
그런데 여기까지 하면 새로 메모를 추가할 때마다 새롭게 메모를 전체 다 불러오는 문제 발생
이를 해결하기 위해 readMemo에 read할 때마다 ul지우도록 명령.
1
2
3
4
5
6
7
| async function readMemo() {
const res = await fetch("/memos");
const jsonRes = await res.json();
const ul = document.querySelector(".memo_ul");
ul.innerHTML = "";
jsonRes.forEach(displayMemo);
}
|
✅ PUT(update)
☑️ FE: JS
클릭되면 수정하는 버튼, displayMemo함수 안에 만들 것
1
2
3
4
5
| const updateBtn = document.createElement("button");
updateBtn.innerText = "update";
li.appendChild(updateBtn);
updateBtn.addEventListener("click", updateMemo);
|
어떤 메모의 updateBtn이 클릭되었는지 알아야되니까 memo의 id를 받아와야 한다.
이를 위해서 displayMemo
함수안에 updateBtn의 dataset의 id를 memo.id로 설정
1
| updateBtn.dataset.id = memo.id;
|
📌 function updateMemo
어떤 memo의 updateBtn이 눌렸는지 알아야 할 것 아니야
updateMemo 함수에서 memo.id받기 eventListener은 항상 event값을 return하니까 이를 받아와 memo id 받아오기 ` const id= event.target.dataset.id;`
수정할 값 입력받기
💡 prompt const updateContent= prompt("How would you like to change your memo?")
수정할 값 받아오기 => request body => PUT
수정 후에는 서버에서 다시 한 번 수정된 array받아와야 하니까 readMemo 호출
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| async function updateMemo(event) {
//get ID of memo to know which memo update btn was clicked
//eventlistener은 항상 event를 return하니까.
const id = event.target.dataset.id;
//뭐라고 수정할지 값 입력받기
const updateContent = prompt("How would you like to change your memo?");
const res = await fetch(`./memos/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: id,
content: updateContent
})
});
readMemo();
}
|
☑️ BE: PYTHON
📌 def update_memo
FE에서 put, request body로 보냈으니까 받아야 함.
@app.put("/memos/{memo_id}")
여기서 /memos/
는 FE에서 설정해 준 경로이다. {memo_id}
는 PATH
해서 받아올 그 값! 을 의미
for문을 사용해
memos라는 array를 빙글빙글 돌면서 item인 memo를 하나씩 꺼내본다. for memo in memos:
if문을 사용해
memo.id
(array에 있는 memo id가) FE에서 받아온 메모의 id req_memo.id
와 같다면, memo.content
(array에 있는 memo content)를 FE에서 받아온 수정 값 req_memo.content
으로 바꾸세요.
1
2
3
4
5
| for memo in memos:
if memo.id == req_memo.id:
memo.content= req_memo.content
return "Update Succeeded"
return "No such Memo"
|
내가 쉽게 설명해 본 코드
1
2
3
4
5
6
| @app.put("/FE에서 설정한 경로memos/{memo_id}")
def update_memo(updateRequestedMemo:Memo):
#memos라는 배열을 쭉 돌면서 for문
for arrayItemMemo in memosArray:
if arrayItemMemo.id ==updateRequestedMemo.id:
arrayItemMemo.content= updateRequestedMemo .content
|
CODE
1
2
3
4
5
6
7
8
9
10
|
@app.put("/memos/{memo_id}")
def update_memo(req_memo:Memo):
#memos라는 배열을 쭉 돌면서 for문
for memo in memos:
if memo.id ==req_memo.id:
memo.content= req_memo.content
return "Update Succeeded"
return "No such Memo"
|
✅ DELETE
☑️ FE: JS:
클릭되면 삭제하는 버튼, displayMemo함수 안에 만들 것
1
2
3
4
5
6
7
8
| //delete button
const deleteBtn = document.createElement("button");
deleteBtn.innerText = "delete";
li.appendChild(deleteBtn);
deleteBtn.addEventListener("click", deleteMemo);
deleteBtn.dataset.id = memo.id;
|
📌 function deleteMemo
삭제할 memo의 id 받아와서 DELETE
method: "DELETE"
는 request body가 아니니까 headers, body모두 필요 없다!
CODE
1
2
3
4
5
6
7
| async function deleteMemo(event) {
const id = event.target.dataset.id;
const res = await fetch(`/memos/{id}`, {
method: "DELETE"
});
readMemo();
}
|
☑️ BE: PYTHON
📌 def delete_memo
array.pop
FE에서 보낸 memo_id를 받는다.
그 아이디 숫자와 일치하는 아이디를 가진 [메모 배열]의 메모를 찾아 배열에서 pop한다.
enumerate
for문에서 두 가지를 돌릴 떄는 enumerate함수를 사용한다.
delete_memo의 경우 메모의 index, memo모두 받기 떄문에 enumerate가 필요하다.
CODE
1
2
3
4
5
6
7
8
9
10
11
| class Memo(BaseModel):
id: str
content: str
@app.delete("/memos/{memo_id}")
def delete_memo(memo_id):
for index, memo in enumerate(memos):
if memo.id == memo_id:
memos.pop(index)
return "memo successfully deleted"
return "no such memo"
|
✅ Trouble Shooting
🔴 Trouble deleteBtn doenst work!!!
🟠 Mistakes I Made_헷갈리거나 실수한 점
백엔드에서 메모 아이디 int로 받으라고 했고, 프론트에서도 잘 보냈으며 create, read, update까지, 그리고 post, put, read메소드는 문제가 없었는데 delete에서 삭제 버튼을 눌러 메모가 지워지지 않는 문제가 생김.
🟡 What I tried_스스로 시도해 본 것들
- memos.pop을 pop말고 clear, remove 써봤지만 안됨
- memos.pop(index)에서 index말고 memo 등 다른 값 넣었지만 안 됨
🟢 What I learned_알게된 점
메모 아이디 값을 int가 아닌 str으로 바꿔주기,
BE에서도 아이디 값을 스트링으로 받아야 함.
이렇게 했더니 해결이 되었고, 이제는 삭제 버튼을 누르면 메모가 잘 삭제된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| async function createMemo(value) {
//post on server
const res = await fetch("/memos", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: toString(new Date().getTime()),
content: value
})
});
readMemo();
}
|
1
2
3
| class Memo(BaseModel):
id: str
content: str
|
✅ 쿼리를 사용해 정렬된 데이터를 서버에서 내려주기
정렬 기준은 가나다ABC순 또는 등록순 2가지 모두 구현 (ex) /memos?sorted=ASC memo에는 다양한 프로퍼티가 있음. (title, createAt 등등) 어떤 프로퍼티를 기준으로 정렬을 시킬건지도 쿼리에 함께 포함
등록일자순 내림차순으로 정렬:
1
| GET /memos?sort_by=created&sort_order=desc
|
제목순 오름차순으로 정렬:
1
| GET /memos?sort_by=title&sort_order=asc
|