당신은 멋쟁이, 우리는 장고쟁이~

0%

TodoList 12편 - 투두리스트 삭제 기능 구현

Todo List - 투두리스트 삭제 기능 구현


투두 리스트 삭제 기능을 추가해 보려 합니다.


삭제 버튼은, 투두리스트 페이지와,


투두리스트 디테일 페이지에 추가해 줄겁니다.


DeleteView 를 사용하기 때문에,

삭제 버튼을 누르면, ‘정말 삭제하겠습니까?’ 라는 문구를 가진 컨펌 페이지가 뜨고,
한번 더 삭제하기 버튼을 누르면,
삭제가 완료되고.

취소 버튼을 누르면, 다시 투두리스트 리스트 페이지로 가게 됩니다.



DeleteView 는 클래스 기반 뷰로,

기본적으로, 정말로 삭제할것인지에 대한 컨펌 페이지를 가지고 있어서

삭제 버튼을 눌렀을때, 이 컨펌 페이지를 거쳐서 삭제를 눌러야

객체가 삭제 됩니다.


구현 과정은 아래와 같습니다.


  1. todo/views.py 파일에 DeleteView 클래스를 추가

  2. templates/todo/delete.html 파일 생성및 작성

  3. templates/todo/todolist_list.html 파일 수정 (삭제버튼 설정)

  4. templates/todo/todolist_detail.html 파일 수정 (삭제버튼 설정)

  5. todo/urls.py 파일에서 delete URL 설정



todo/views.py 파일에 DeleteView 클래스 추가



1
2
3
4
class DeleteView(generic.DeleteView):
model = TodoList
success_url = '/'
tempalte_name = 'todo/delete.html'


templates/todo/delete.html 파일 생성 및 작성



1
2
3
4
5
6
base.html 상속받는 대신에, {% load static %} 을 사용하여, 
static 폴더 안에 있는 style.css 파일을 직접 가져와 사용했습니다.

DeleteView 를 사용하기 때문에, {{ form }} 을 사용하여, 삭제 폼을 만들어 주었고,

삭제 버튼과 취소 버튼을 만들어 주었습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'bulma/css/style.css' %}">

<div class="field is-grouped is-grouped-centered">
<p>{{ object }}</p><br><br>

</div>

<div class="field is-grouped is-grouped-centered">

<form action="" method="POST">

{{ form }}
{% csrf_token %}

<p class="control">

<input type="submit" class="button is-danger" value="삭제">
<a class="button is-light" href="{% url 'todo:todolist' %}">
취소
</a>
</p>
</form>
</div>

<div class="field is-grouped is-grouped-centered">

<p class="control">
해당 투두리스트를 삭제 하시겠습니까?
</p>
</div>

templates/todo/todolist_list.html 파일 수정


1
2
3
4
5
6
7
8
삭제하기 버튼을 누르면, "/delete/{{ todo.id }}" url 로 넘어가서, 
DeleteView 를 호출할것입니다.

<footer class="card-footer">
<a href="/detail/{{ todo.id }}" class="card-footer-item"><button class="button is-primary is-fullwidth">더보기</button></a>
<a href="#" class="card-footer-item"><button class="button is-warning is-fullwidth">수정하기</button></a>
<a href="/delete/{{ todo.id }}" class="card-footer-item"><button class="button is-danger is-fullwidth">삭제하기</button></a>
</footer>


templates/todo/todolist_detail.html 파일 수정


1
2
3
4
5
6
7
8
9
10
삭제하기 버튼을 누르면, "/delete/{{ todo.id }}" url 로 넘어가서, 
DeleteView 를 호출하게 해서,


Detail 페이지에서도 삭제가 가능하게 하려 했지만,


DeleteView 를 Detail 페이지에서 호출하면, 에러가 납니다. (이에 대한 해결 방법을 찾지 못하고 있음)

따라서, 삭제 버튼을 누르면, 다시 리스트 페이지로 되돌아오게 해주었습니다..

1
2
3
4
5
<footer class="card-footer">
<a href="{% url 'todo:todolist' %}" class="card-footer-item"><button class="button is-link is-fullwidth">뒤로가기</button></a>
<a href="#" class="card-footer-item"><button class="button is-warning is-fullwidth">수정하기</button></a>
<a href="{% url 'todo:todolist' %}" class="card-footer-item"><button class="button is-danger is-fullwidth">삭제하기</button></a>
</footer>

todo/urls.py 파일에서 delete URL 설정


‘delete/int:pk/‘ 라는 URL 을 가지면, DeleteView 를 호출하고,

삭제 페이지로 넘어가게 됩니다.


1
2
3
4
5
6
7
8
9
10
11
from django.contrib import admin
from django.urls import path
from .views import IndexView, DetailView, DeleteView

app_name = 'todo'

urlpatterns = [
path('', IndexView.as_view(), name='todolist'),
path('detail/<int:pk>/', DetailView.as_view(), name="todolist_detail"),
path('delete/<int:pk>/', DeleteView.as_view(), name="todolist_delete"),
]


마치며..


서버를 시작하고, 삭제 테스트를 해봅니다.


투두 리스트 페이지에서 삭제 진행



삭제 버튼을 누르면, 아래 컨펌 페이지가 뜨고, 여기서 한번 더 삭제를 누르면 객체가 삭제 완료 됩니다.



삭제 버튼을 누르면, 투두리스트 삭제가 진행 되는것을 확인 하였습니다만.

디테일 페이지에서 삭제 동작을 구현하지 못한것이 아쉽습니다.
클래스 베이스 뷰에 있는 DeleteView 를 더 많이 경험해 봐야 알것 같습니다.



만약, DeleteView 를 사용하지 않고, 함수형으로 이 기능을 구현하고 싶다면,



views.py 에 아래와 같은 함수를 작성하고, 적절히 URL 을 연결하여 사용하면 됩니다.


1
2
3
4
5
# views.py 
def delete_todo(request, pk):
t = TodoList.objects.get(pk=pk)
t.delete()
return redirect('/')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# todo/urls.py 
from django.contrib import admin
from django.urls import path
from .views import IndexView, DetailView, DeleteView, UpdateView, TodoCreate
from .views import delete_todo
app_name = 'todo'

urlpatterns = [
path('', IndexView.as_view(), name='todolist'),
path('detail/<int:pk>/', DetailView.as_view(), name="todolist_detail"),
path('delete/<int:pk>/', DeleteView.as_view(), name="todolist_delete"),
path('delete_todo/<int:pk>/', delete_todo, name="delete_todo"),
path('update/<int:pk>/', UpdateView.as_view(), name='todolist_update'),
path('create/', TodoCreate, name='todolist_create'),
]



다만, 이렇게 구현 하면, DeleteView 를 사용했을때랑은 다르게,

Confirm page 가 나오지 않고. 바로 삭제가 됩니다.