Templates
코딩하기 전, 참고사항이 있다.
URL 패턴 | 뷰 이름 | 템플릿 파일명 |
---|---|---|
/admin/ | (장고 기본제공) | |
/todo/vonly/ | TodoVueOnlyTV(TemplateView) | todo_vue_only.html |
/todo/create/ | TodoCV(CreateView) | todo_form.html |
/todo/list/ | TodoLV(ListView) | todo_list.html |
/todo/99/delete/ | TodoDelV(DeleteView) | todo_confirm_delete.html |
코딩 순서를 잡을 때 현재는 클래스 뷰 3개를 만들고 다음은 템플릿 3개를 만드는 방식으로 설명하고 있지만,
그렇지 않고 CreateView 다음에 todo_form, 뷰 다음 템플릿 으로 각 기능별로 코딩 순서를 잡을수도 있다.
이번에서는 한번에 뷰 3개를, 템플릿 파일 3개를 작업할 필요는 없다. 필요에 의해 기능별로 작업하면 된다.
root/todo/templates/todo/todo_form.html
루트 경로에 todo 앱 폴더 templates 폴더 안 todo 폴더안에 작업했던 todo_vue_only.html
파일이 있는 곳에 만든다.
해당 소스는 todo_vue_only.html의 코드를 복사해 붙여넣고, vuejs 소스코드를 삭제한다.
<style>
body {
text-align: center;
background-color: #ddd;
}
.inputBox {
margin: auto;
width: 70%;
background: white;
height: 50px;
border-radius: 50px;
line-height: 50px;
}
.inputBox .name {
border-style: none;
border-bottom: 1px solid #ddd;
width: 70px;
padding-left: 20px;
}
.inputBox .item {
border-style: none;
border-bottom: 1px solid #ddd;
width: 400px;
margin-left: 50px;
padding-left: 20px;
}
.todoList {
list-style: none;
padding: 10px 0;
text-align: left;
}
.todoList li {
display: flex;
height: 50px;
line-height: 50px;
margin: 0.5rem 0;
padding: 0 0.9rem;
background: white;
border-radius: 5px;
}
.addBtn {
cursor: pointer;
background-color: #cc8800;
color: #ffffFF;
border-radius: 15px;
border-color: #445566;
}
.removeBtn {
margin-left: auto;
font-size: 20px;
cursor: pointer;
}
</style>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue-Django ToDo App</title>
</head>
<body>
<div id='app'>
<h1>My Todo App !</h1>
<strong>서로 할 일이나 의견을 공유해 봅시다.</strong>
<br>
{# csrf 토큰 공격을 방지하는 csrf 토큰을 넣는다. 장고에서 제공해주는 템플릿 태그이다. #}
<form class="inputBox" action="." method="post"> {% csrf_token %}
<input class="name" type="text" placeholder="name ..." name="name">
<input class="item" type="text" placeholder="type anything welcomed ..."
name="todo">
<button class="addBtn" type="submit">ADD</button>
</form>
</div>
</body>
</html>
csrf 공격을 방지하는 csrf 토큰을 넣는다. {% csrf_token %}
여기까지 완료했다면 화면에 잘 나오는지 우리가 만들었던 url path로 들어가서 확인해본다.
http://127.0.0.1:8000/todo/create/
페이지가 잘 뜨는지 확인하고, create까지 정상적으로 되는지 입력하고 ADD버튼을 누르면
아래와 같은 오류 페이지가 뜨는데, create는 정상적으로 되었지만 todo/list 기능을 완료하지 않았기 때문에 redirect가 되지않는 오류가 발생한 것이다.
간단하게todo_list.html
을 만든다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List</title>
</head>
<body>
todo list html..
</body>
</html>
이 후 다시 브라우저에서 add 후 페이지가 정상적으로 Redirect가 되는지 확인해보면 에러없이 잘 랜더링 되는것을 확인할 수 있다.
todo_list.html
코딩하기마찬가지로 todo_vue_only.html
코드를 복사 후 <div class="inputBox">
인풋 부분을 다 지우고, vuejs 코드와 <scripts>
부분을 전부 지워준다.
<body>
<div id='app'>
<h1>My Todo App !</h1>
<strong>서로 할 일이나 의견을 공유해 봅시다.</strong>
<br>
<ul class="todoList">
{# v-for문 대신에, 장고에서 제공하는 템플릿 태그로 바꾼다. #}
{% for todo in object_list %}
<li>
<span>{{ todo.name }}::: {{ todo.todo }}</span>
<span class="removeBtn"><a href="{% url 'todo:delete' todo.id %}">×</a></span>
</li>
{% endfor %}
</ul>
</div>
</body>
v-for문 대신에, 장고에서 제공하는 템플릿 태그로 바꾼다. 삭제를 했을 때의 액션 태그도 넣는다.
<span class="removeBtn"><a href="{% url 'todo:delete' todo.id %}">×</a></span>
이 코드는 삭제버튼을 클릭하면 delete하고, 파라미터 값으로 todo.id를 넘긴다는 의미이다.
여기까지 완료되었으면 마찬가지로 todo/create url에서 생성하고, 리스트에 잘 나오는지 테스트한다.
admin 페이지에서도 (/admin/todo/todo/) 데이터가 잘 쌓이고 있는지도 확인하면 좋다.
todo_confirm_delete.html
코딩하기여태했던 방식으로 복사 후 붙여넣고 script태그와 코드를 지우고, 사용하지 않는 css는 정리하면 좋다.
그리고 body 내에 코드를 아래와 같이 정리한다.
<body>
<div id='app'>
<h1>Todo Delete</h1>
<p>
Are you sure to delete {{ object }} ?
</p>
<br>
<form action="." method="post"> {% csrf_token %}
<button type="submit">Confirm</button>
</form>
</div>
</body>
여기까지 완료했다면 삭제처리 테스트를 진행한다.
리스트 뷰 페이지에서 삭제 버튼 클릭 -> delete confirm 페이지에서 컨펌 버튼 클릭 -> 리스트 화면에서 삭제된 화면
이렇게 정상적인 프로세스로 테스트가 완료되었다.
현재 create 뷰에서 name에 데이터를 넣지않고 내용만 작성하면 이름이 나오지 않는데, 기본 Default 이름을 설정하도록 수정하겠다.
이런 기능은 데이터베이스에서 세이브할 때 넣을 수 있고, form 처리하면서 넣을 수 있다.
백엔드가 처리하는 과정에서 데이터베이스 세이브 하면서 넣는게 일반적인 방법이다.
models.py
파일에서 save 메소드를 오버라이드하여 추가한다.
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
if not self.name: # self.name의 값이 없다면
self.name = '홍길동'
super().save()
# 상위 클래스의 save 메소드를 호출하는 것을 잊지않을 것.
완료 했다면, 이름 없이 작성하여 리스트에서 정상적으로 처리가 되는지 테스트한다.
여기까지 create, list, delete 세 가지 기능이 완료되었다.
전체적으로 플로우를 따라 한번씩 테스트 하면서 프로세스가 어떻게 돌아가는지 한 번 되새기면서 생각하는 것이 좋다.
GitHub Source
👉🏻깃허브 소스