파이썬 pip / 가상환경에서 이어지는 내용
/home/user/Projects/flask-tutorial
├── flaskr/
│ ├── __init__.py
│ ├── db.py
│ ├── schema.sql
│ ├── auth.py
│ ├── blog.py
│ |── templates/ <<<<
│ │ ├── base.html <<<<
│ │ ├── auth/
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ └── blog/
│ │ ├── create.html
│ │ ├── index.html
│ │ └── update.html
│ └── static/
│ └── style.css
├── tests/
│ ├── conftest.py
│ ├── data.sql
│ ├── test_factory.py
│ ├── test_db.py
│ ├── test_auth.py
│ └── test_blog.py
├── .venv/
├── pyproject.toml
└── MANIFEST.in
flask에서 안내하는 프로젝트 마지막의 디렉토리 모습입니다.
templates 디렉토리안에 index.html를 생성하고 app.py에서 연결해줍니다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello():
return render_template('index.html')
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)
http://localhost:5000
에서 html과 app.py가 연결됐는지 확인
<div class="wrap">
<h1>To Do List</h1>
<input class="todo-input" type="text" placeholder="todo 입력">
<input class="update-input" type="text" placeholder="수정">
<ul class="todo-list"></ul>
</div>
crud에서 가장 기본적인 to do list를 만들어봅니다.
css는 기본적인 틀을 제외하고 생략합니다.
데이터를 읽을 수 있는 api를 먼저 작성합니다.
즉, 데이터 저장이 먼저입니다.
클라이언트가 없는 지금 api 요청과 응답을 제대로 확인할 수 없기 때문에 Postman 혹은 vscode의 Thunder Client를 사용합니다.
# 생성 post 요청
@app.route('/createTodo', methods=['POST'])
def toDo_create():
todo_receive = request.form['todo_give']
doc = {
'todo': todo_receive,
}
todos.insert_one(doc)
print('post toDo 저장', doc)
return jsonify({'msg': 'app.py > post 요청 create'})
서버가 켜져있는지 확인하고 Thunder Client 이용해서 값을 보내고 응답을 확인합니다.
클라이언트에서 값을 보내줄 때 FormData에 담아 보내주기 때문에 Form에 테스트 값을 입력하고 응답을 확인합니다.
# 읽기 get 요청
@app.route("/readToDo", methods=["GET"])
def toDo_get():
all_todo = list(todos.find({},{'_id':False}))
return jsonify({'msg': all_todo})
값을 성공적으로 저장했으면 값을 가져와야합니다.
# 삭제 delete 요청
@app.route('/deleteTodo', methods=['DELETE'])
def toDo_delete():
todo_receive = request.form['todo_give']
todos.delete_one({'todo': todo_receive})
return jsonify({'msg': 'app.py > delete 요청'})
현재 todo의 값을 받아와 값에 해당하는 데이터를 삭제합니다.
# 수정 post 요청
@app.route('/updateToDo', methods=['POST'])
def toDo_update():
currentToDo_receive = request.form['current_todo']
todo_receive = request.form['todo_change']
todos.update_one({'todo': currentToDo_receive},{'$set':{'todo': todo_receive}})
return jsonify({'msg': 'app.py > post 요청 update'})
현재 입력된 값을 확인하고 받아와 DB에서 찾은 후 해당 값을 새로운 입력값으로 변경
// 공통 코드
// todo 입력
const toDoInput = document.querySelector(".todo-input");
// todo 변경
const updateInput = document.querySelector(".update-input");
// todo print container
const toDoList = document.querySelector(".todo-list");
// 모든 투두 가져오는 함수
const printAllToDo = () => {
console.log("printAllToDo 함수 실행");
const rUrl = "/readToDo";
fetch(rUrl)
.then((res) => {
if (!res.ok) {
throw new Error(
`This is an HTTP error: The status is ${response.status}`
);
}
return res.json();
})
.then((data) => {
let toDos = data.msg;
console.log(data);
toDos.forEach((todo) => {
const todoLi = document.createElement("li");
todoLi.classList.add("todoLi");
const delSpan = document.createElement("span");
delSpan.addEventListener("click", deleteToDoFn);
delSpan.classList.add("del");
const updateDiv = document.createElement("div");
updateDiv.addEventListener("click", updateToDo);
const todoSpan = document.createElement("span");
updateDiv.innerText = "수정";
todoSpan.innerText = todo.todo;
delSpan.innerText = "삭제";
todoLi.append(todoSpan);
todoLi.append(delSpan);
todoLi.append(updateDiv);
toDoList.append(todoLi);
});
})
.catch((err) => {
console.log(err.message);
});
};
// 스크립트 실행시 투두 프린트
printAllToDo();
로드완료시 함수 바로 실행
fetch(get)로 데이터를 가져와 태그를 생성하고 프린트
// 투두 생성 함수
const createTodoFn = () => {
let inputVal = toDoInput.value;
let formData = new FormData();
formData.append("todo_give", inputVal);
fetch("/createTodo", { method: "POST", body: formData })
.then((res) => res.json())
.then((data) => {
console.log("데이터 생성 완료", data);
inputVal = null;
location.reload();
});
};
// 이벤트
toDoInput.addEventListener("keydown", (e) => {
if (e.keyCode === 13) {
createTodoFn();
}
});
입력값 데이터를 서버로 넘겨줌
// 투두 삭제 함수
const deleteToDoFn = (e) => {
let deleteToDoVal = e.target.previousSibling.innerText;
let formData = new FormData();
formData.append("todo_give", deleteToDoVal);
fetch("/deleteTodo", { method: "DELETE", body: formData })
.then((res) => res.json())
.then(() => {
location.reload();
});
};
선택된 데이터를 삭제
// 투두 수정 함수
const updateToDo = (e) => {
let updateToDo = e.target.previousSibling.previousSibling.innerText;
const current_todo = updateToDo;
updateInput.classList.add("show");
toDoInput.classList.add("close");
updateInput.focus();
updateInput.value = updateToDo;
updateInput.addEventListener("keydown", (e) => {
if (e.keyCode === 13) {
let formData = new FormData();
formData.append("current_todo", current_todo);
formData.append("todo_change", updateInput.value);
fetch("/updateToDo", { method: "POST", body: formData })
.then((res) => res.json())
.then(() => {
location.reload();
});
}
});
};
선택된 데이터를 확인하고 변경된 데이터로 변경