[Flask] 3-10 게시물 수정 & 삭제

2023. 12. 3. 20:23Web/Flask

728x90

이번에는 작성한 게시물을 수정 & 삭제할 수 있는 기능을 추가할 것이다

진행하다 보면 "비슷한 기능을 반복해서 구현한다는 느낌"을 받아 조금 지루할 수 있다

게시물 수정 & 삭제 기능은 게시물 작성만큼 중요하다

 

수정 일시

질문, 답변을 언제 수정했는지 확인할 수 있도록

Question 모델과 Answer 모델에 modify_date 속성을 추가하자

[파일명: projects/myproject/pybo/models.py]

modify_date 속성에는 nullable=True로 null을 허용하도록 했다

수정일시는 수정이 발생할 경우에만 생성되므로 null을 허용해야 한다

 

모델이 변경되었으므로 migrate, upgrade 명령을 수행하자

 

질문 수정 버튼

질문 상세 화면에 다음과 같이 질문 수정 버튼을 추가하자

[파일명: projects/myproject/pybo/templates/question/question_detail.html]

질문 수정 버튼은 로그인한 사용자와 글쓴이가 같은 경우에만

보여야 하므로 {% if g.user == question.user %}를 사용했다

 

질문 수정 라우팅 함수

질문 상세 템플릿에 url_for('question.modify', question_id=question.id) URL이 추가되었으니

아래 같은 modify 함수를 작성해야 한다

[파일명: projects/myproject/pybo/views/question_views.py]

질문 수정은 로그인이 필요하므로 @login_required 애너테이션을 추가했다

만약 로그인한 사용자와 질문의 작성자가 다르면 수정할 수 없도록

flash 오류를 발생시키는 코드도 추가했다

 

modify 함수가 GET 방식으로 요청되는 경우는 <질문수정> 버튼을 눌렀을 때다

이때 수정할 질문에 해당하는 "제목", "내용" 등의 데이터가 화면에 보여야 한다

 데이터베이스에서 조회한 데이터를 템플릿에 적용하는 가장 간단한 방법은 QuestionForm(obj=question)과 같이 조회한 데이터를 obj 매개변수에 전달하여 폼을 생성하는 것이다

이렇게 하면 QuestionForm의 subject, content 속성에 question 객체의 subject, content 값이 저장되어 화면에도 표시된다

 

modify 함수가 POST 방식으로 요청되는 경우는 질문 수정 화면에서

데이터를 수정한 다음 <저장하기> 버튼을 눌렀을 경우다

form.validate_on_submit 함수에서 QuestionForm을 검증하고 아무 이상이 없으면 변경된 데이터를 저장한다

데이터 변경을 위해 입력한 form.populate_obj(question)는 form 변수에 들어 있는

데이터(화면에서 입력한 데이터)를 question 객체에 업데이트 하는 역할을 한다

 

오류 표시

flash 에 의해 발생되는 "수정권한이 없습니다"라는 오류가 표시될수 있도록

질문 상세 화면 위쪽에 오류 영역을 추가하자

[파일명: projects/myproject/pybo/templates/question/question_detail.html]

물론 수정은 로그인 한 사용자와 글 작성자가 동일한 경우에만 가능하기 때문에 이 오류가 표시될 일은 없을 것이다

하지만 비 정상적인 방법으로 질문을 수정할 경우 오류를 보여주어야 하므로 필요한 부분이다

 

질문 수정 확인

이제 로그인한 후에 질문을 수정해 보자

이때 로그인한 사용자와 글쓴이가 같아야 한다

그렇지 않으면 <수정> 버튼이 보이지 않는다

 

질문 삭제 버튼

이번에는 작성한 글을 삭제할 수 있는 버튼을 다음처럼 추가해 보자

[파일명: projects/myproject/pybo/templates/question/question_detail.html]

<삭제> 버튼은 <수정> 버튼과는 달리 href 속성값을 "javascript:void(0)"로 설정했다

그리고 삭제를 실행할 URL을 얻기 위해 data-uri 속성을 추가하고

<삭제> 버튼이 눌리는 이벤트를 확인할 수 있도록 class 속성에 "delete" 항목을 추가해 주었다

 

href에 삭제 URL을 직접 사용하지 않고 이러한 방식을 사용하는 이유는

삭제 버튼을 클릭했을때 "정말로 삭제하시겠습니까?" 와 같은 확인창이 필요하기 때문이다

 

자바스크립트

삭제 버튼을 눌렀을때 확인창을 호출하기 위해서는

아래 같은 자바스크립트 코드가 필요하다

이 자바스크립트의 의미는 delete라는 클래스를 포함하는 컴포넌트(예:버튼이나 링크)를 클릭하면

"정말로 삭제하시겠습니까?" 라는 질문을 하고 "확인"을 선택했을때

해당 컴포넌트의 data-uri 값으로 URL 호출을 하라는 의미이다

 

따라서 이와 같은 스크립트를 추가하면 "삭제" 버튼을 클릭하고 "확인"을 선택하면

data-uri 속성에 해당하는 {% url 'pybo:question_delete' question.id %} URL이 호출될 것이다

이 코드는 아직 추가하지는 않는다

 

자바스크립트 블록

자바스크립트는 HTML 구조에서 아래 같이 </body> 태그 바로 위에 삽입하는 것이 좋다

이유는 이렇게 하면 화면 렌더링이 완료된 후에 자바스크립트가 실행되기 때문이다

화면 렌더링이 완료되지 않은 상태에서 자바스크립트를 실행하면 화면의 값을 읽지 못하는

오류가 발생할수도 있고 화면 로딩이 지연되는 문제가 발생할 수도 있다

따라서 자바스크립트는 </body> 태그 바로 위에 삽입하는 것이 좋다

 

자바스크립트를 </body> 태그 바로 위에 삽입하기 위해 아래처럼 base.html을 수정하자

[파일명: projects/myproject/pybo/templates/base.html]

base.html 을 상속하는 템플릿들에서 content 블록을 구현하게 했던것과 같은 방법으로

script 블록을 구현할수 있도록 했다

</body> 태그 바로 위에 {% block script %}{% endblock %} 블록을 추가했다

 이렇게 하면 이제 base.html을 상속하는 템플릿은 자바스크립트의 삽입 위치를 신경쓸 필요없이

스크립트 블록을 사용하여 자바스크립트를 작성하면 된다

 

question_detail.html 하단에 {% block script %}{% endblock %} 블록을 아처럼 추가하자

[파일명: projects/myproject/pybo/templates/question/question_detail.html]

{% block script %} {% endblock %} 사이에 질문을 삭제할 수 있는 자바스크립트를 작성하였다

 

질문 삭제 라우팅 함수

앞서 질문 상세 템플릿에 작성한 data-uri 속성에 url_for('question.delete', question_id=question.id) URL이

추가되었으므로 질문을 삭제할 수 있도록 라우팅 함수 delete를 추가해야 한다

[파일명: projects/myproject/pybo/views/question_views.py]

delete 함수 역시 로그인이 필요하므로 @login_required 애너테이션을 적용하고

로그인한 사용자와 글쓴이가 같은 경우에만 질문을 삭제할 수 있도록 했다

 

질문 삭제 확인

이제 질문 작성자와 로그인 사용자가 같으면 질문 상세 화면에 <삭제> 버튼이 나타난다

 

답변 수정 버튼

답변 목록이 출력되는 부분에 답변 수정 버튼을 추가하자

[파일명: projects/myproject/pybo/templates/question/question_detail.html]

 

답변 수정 라우팅 함수

url_for('answer.modify', answer_id=answer.id) URL을 추가했으므로

answer_views.py 파일에 modify 함수를 추가하자

[파일명: projects/myproject/pybo/views/answer_views.py]

 

답변 수정 템플릿

답변 수정에 사용할 answer_form.html 파일은 아처럼 작성하자

[파일명: projects/myproject/pybo/templates/answer/answer_form.html]

답변 내용을 확인하고 수정할 수 있는 간단한 템플릿이다

 

답변수정 확인

질문과 마찬가지로 답변도 등록한 사용자와 로그인한 사용자가 같아야 <수정> 버튼이 나타난다

답변을 작성한 뒤 <수정> 버튼을 누르면 답변 수정화면으로 이동한다

답변 삭제 버

질문 상세 템플릿에서 답변을 삭제할 수 있는 버튼을 다음과 같이 추가하자

[파일명: projects/myproject/pybo/templates/question/question_detail.html] Copy

<수정> 버튼 옆에 <삭제> 버튼을 추가했다

질문의 <삭제> 버튼과 마찬가지로 <삭제> 버튼에 delete 클래스를 적용했으므로 <삭제> 버튼을 누르면

data-uri 속성에 설정한 url이 실행될 것이다

 

답변 삭제 라우팅 함수

url_for('answer.delete', answer_id=answer.id) URL을 추가했으므로 answer_views.py 파일에 delete 함수를 작성하자

[파일명: projects/myproject/pybo/views/answer_views.py]

delete 함수 역시 로그인이 필요하므로 @login_required 애너테이션을 추가했다

 

답변 삭제 확인

이제 질문 상세 화면에서 답변을 작성한 사용자와 로그인한 사용자가 같으면

<삭제> 버튼이 나타날 것이다

삭제 기능이 잘 동작하는지 확인해 보자

 

수정일시 표시하기

마지막으로 질문 상세 화면에서 수정일시를 확인할 수 있도록 템플릿을 수정해 보자

 질문과 답변에는 이미 작성일시를 표시하고 있다

작성일시 바로 왼쪽에 수정일시를 추가하자

[파일명: projects/myproject/pybo/templates/question/question_detail.html]

 

이제 질문이나 답변을 수정하면 아처럼 수정일시가 표시될 것이다

728x90

'Web > Flask' 카테고리의 다른 글

[Flask] 3-12 앵커  (1) 2023.12.03
[Flask] 3-11 추천 기능 추가하기  (2) 2023.12.03
[Flask] 3-9 글쓴이 표시하기  (1) 2023.12.03
[Flask] 3-8 모델 수정하기  (0) 2023.12.02
[Flask] 3-7 로그인과 로그아웃  (0) 2023.12.02