2020-04-11

Django 23. 게시글 수정 / 삭제 구현

글수정을 구현하고 글을 삭제할 때 경고창을 띄운 후 삭제하도록 구현합니다.


1. 글 수정 View 작성

이 프로젝트에서 글을 수정할 수 있는 권한은 최고권한인 level 0의 개발자 권한과, 글 작성자 본인으로 설정하고, 이전에 생성한 글쓰기 폼인 noticeWriteView를 사용하여 구현합니다. notice appviews.py에 아래의 소스를 입력합니다.

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
# notice/views.py

@login_message_required
def notice_edit_view(request, pk):
notice = Notice.objects.get(id=pk)

if request.method == "POST":
if(notice.writer == request.user or request.user.level == '0'):
form = NoticeWriteForm(request.POST, instance=notice)
if form.is_valid():
notice = form.save(commit = False)
notice.save()
messages.success(request, "수정되었습니다.")
return redirect('/notice/'+str(pk))
else:
notice = Notice.objects.get(id=pk)
if notice.writer == request.user or request.user.level == '0':
form = NoticeWriteForm(instance=notice)
context = {
'form': form,
'edit': '수정하기',
}
return render(request, "notice/notice_write.html", context)
else:
messages.error(request, "본인 게시글이 아닙니다.")
return redirect('/notice/'+str(pk))

로그인한 사용자만 접근이 가능하도록 decorator를 추가하고, 글 수정을 개발자와 글작성자만 가능하게 하기 위해 GET, POST 요청 후에 검사를 진행하고 현재 접속 사용자와 글의 작성자가 일치하지 않으면 에러 메세지를 출력합니다

글 수정 view는 해당 게시글의 pk값인 id를 파라미터로 받습니다. 사용자가 게시글에서 글 수정 버튼을 클릭할 시 GET으로 글쓰기 폼을 context에 담아 넘겨줍니다. 기존의 제목과 내용 등 값들을 그대로 넘겨주기 위해 instance = 객체 형식으로 폼을 전달합니다. 또한 ‘’작성하기’’ 버튼 Text 대신 ‘’수정하기’’로 변경하기 위해 context에 담아 템플릿에 전달합니다.

글 수정 POST요청 또한 마찬가지로 권한 검사를 진행한 후 폼에 입력된 값들을 전달받아 is_valid가 통과되면 저장 후 성공 메세지를 출력합니다.

2. 글 삭제 View 작성

글 삭제 view 또한 글 수정과 마찬가지로 게시글의 pk값을 파라미터로 받고 권한 검사를 진행합니다. 아래와 같이 DB의 해당 row객체를 삭제하기 위해 delete() 메소드를 사용하는 소스를 입력합니다.

1
2
3
4
5
6
7
8
9
10
11
12
# notice/views.py

@login_message_required
def notice_delete_view(request, pk):
notice = Notice.objects.get(id=pk)
if notice.writer == request.user or request.user.level == '0':
notice.delete()
messages.success(request, "삭제되었습니다.")
return redirect('/notice/')
else:
messages.error(request, "본인 게시글이 아닙니다.")
return redirect('/notice/'+str(pk))

3. 본인 게시글 확인 context 추가

사용자가 특정 게시글에 접근했을때 글 작성자 본인이 아니면 수정과 삭제 버튼을 보이지 않게 하기 위해 게시글상세보기 포스팅에서 구현한 notice_detal_view에 아래의 소스를 추가합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# notice/views.py

def notice_detail_view(request, pk):
notice = get_object_or_404(Notice, pk=pk)

if request.user == notice.writer:
notice_auth = True
else:
notice_auth = False

context = {
'notice': notice,
'notice_auth': notice_auth,
}

해당 게시글의 작성자인 notice.writer와 현재 접속 사용자인 request.user를 비교하여 일치하면 context로 True를 전달하고, 불일치시 False를 전달합니다.

4. urls.py 작성

글 수정 view와 글 삭제 view를 연결하기 위해 urls.pyurlpatterns에 아래의 경로를 추가합니다.

1
2
3
4
5
6
# notice/urls.py

urlpatterns = [
path('<int:pk>/edit/', views.notice_edit_view, name='notice_edit'),
path('<int:pk>/delete/', views.notice_delete_view, name='notice_delete'),
]

5. templates 수정

게시글의 작성자가 아니라면 수정, 삭제버튼이 생성되지 않게 하기 위해 앞서 context에 담아 전달받은 notice_auth를 사용합니다. 이전에 생성한 notice_detail.html에 아래의 소스를 추가합니다.

1
2
3
4
5
6
7
8
<!-- templates/notice/notice_detail.html -->

<div>
{% if notice_auth or request.user.level == '0' %}
<button class="btn btn-sm" onclick="location.href='/notice/{{ notice.id }}/edit/'">수정</button>
<button class="btn btn-sm" data-toggle="modal" data-target="#delete_modal">삭제</button>
{% endif %}
</div>

해당 게시글의 작성자가 아니라면 notice_authFalse가 되어 수정과 삭제 버튼이 출력되지 않습니다. 수정 버튼은 onclick 이벤트로 해당 게시글의 id값 경로로 이동할 수 있게 하고, 삭제 버튼은 사용자가 삭제버튼을 클릭할 시 바로 삭제되지 않고 삭제경고창을 출력 후 진행하기 위해 Bootstrap modal을 활용합니다.

notice_wirite.html에 아래의 소스를 추가하여 앞서 구현한 글 수정 view에서 context로 전달된 edit 객체를 사용해 수정하기 상태라면 작성하기 텍스트 대신 수정하기 텍스트로 표시되게 합니다.

1
2
3
4
5
6
7
8
9
<!-- templates/notice/notice_write.html -->

<div>
{% if edit %}
<button type="submit" class="btn btn-sm">{{ edit }}</button>
{% else %}
<button type="submit" class="btn btn-sm">작성하기</button>
{% endif %}
</div>

6. 글 삭제 경고창 구현

삭제 버튼을 클릭시 팝업되는 modal창 소스는 아래와 같습니다. notice_detail.html에 해당 게시글 id값의 삭제 url로 이동하는 스크립트와 함께 추가합니다.

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
<!-- templates/notice/notice_detail.html -->

<div id="delete_modal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">삭제경고</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>게시글을 삭제하시겠습니까?</p>
</div>
<div class="modal-footer">
<button onclick="delete_modal()" type="button" class="btn btn-dark">삭제하기</button>
<button type="button" class="btn btn-light" data-dismiss="modal">취소하기</button>
</div>
</div>
</div>
</div>

<script type="text/javascript">
function delete_modal() {
location.replace('/notice/{{ notice.id }}/delete/');
}
</script>

7. 결과

django-project-23

*전체 html, css 등은 자세하게 포스팅하지 않습니다. 제 Github에서 소스를 확인하실 수 있습니다.