책 '점프 투 플라스크'를 공부하면서 정리한 내용입니다.
출처 : https://wikidocs.net/81060
modify_date = db.Column(db.DateTime(), nullable=True)
수정일시는 수정이 발생할 경우에만 생성하므로 null을 허용하도록 했다.
모델이 변경되었으므로 migrate, upgrade 명령을 수행한다.
question_detail.html에 질문 수정 버튼 추가
{% if g.user == question.user %}
<div class="my-3">
<a href="{{ url_for('question.modify', question_id=question.id) }}"
class="btn btn-sm btn-outline-secondary">수정</a>
</div>
{% endif %}
질문 수정 버튼은 로그인한 사용자와 글쓴이가 같은 경우에만 보여야 하므로 {% if g.user == question.user %}와 같이 추가한다.
question_detail.html에 url_for('question.modify', question_id=question.id) URL이 추가되었으니 question_views.py에 modify 함수를 만들어야 한다.
modify 함수가 GET 방식으로 요청되는 경우 : <질문수정> 버튼을 눌렀을 경우(question_form.html 템플릿 렌더링) 이 때 이미 수정할 질문에 해당하는 ‘제목’, ‘내용’ 등의 데이터가 보여야 한다. (QuestionForm(obj=question))
modify 함수가 POST 방식으로 요청되는 경우 : 질문 수정 화면에서 데이터를 수정한 다음 <저장하기> 버튼을 눌렀을 경우. form.validate_on_submit 함수에서 QuestionForm을 검증 후 이상 없으면 변경된 데이터 저장.
함수 form.populate_obj(question)
form 변수에 들어 있는 데이터(화면에 입력되어 있는 데이터)를 question 객체에 적용
question_detail.html에서 <수정> 버튼 바로 옆에 <삭제> 버튼 추가
<a href="#" class="delete btn btn-sm btn-outline-secondary"
data-uri="{{ url_for('question.delete', question_id=question.id) }}">삭제</a>
<삭제> 버튼을 눌렀을때 자바스크립트를 호출하도록 class 속성으로 delete 추가. jQuery에서 $(this).data('uri')로 삭제를 실행하는 URL을 얻으려고 data-uri 속성도 추가
<삭제> 버튼을 구현할 때 ‘정말로 삭제하시겠습니까?’와 같은 확인 창 띄우기
<삭제>버튼을 누르면 확인 창이 나타나고, 확인 창에서 <확인> 버튼을 누르면 앞서 입력했던 data-uri 속성값으로 URL 호출이 실행
base.html 파일에 jQuery 로드 관련 코드가 추가되어 있기 때문에 base.html 파일을 수정한다.
<!-- 자바스크립트 Start -->
{% block script %}
{% endblock %}
<!-- 자바스크립트 End -->
question_detail.html 파일 아래에 {% block script %}{% endblock %} 블록을 추가하고 질문을 삭제할 수 있도록 코드를 추가
<script type='text/javascript'>
$(document).ready(function(){
$(".delete").on('click', function() { // 클래스값이 delete인 엘리먼트가 눌리면?
if(confirm("정말로 삭제하시겠습니까?")) { // 확인 창이 열림
location.href = $(this).data('uri'); // data-uri 속성값으로 URL 호출
}
});
});
</script>
question_views.py에 delete 추가
@bp.route('/delete/<int:question_id>')
@login_required
def delete(question_id):
question = Question.query.get_or_404(question_id)
if g.user != question.user:
flash('삭제권한이 없습니다')
return redirect(url_for('question.detail', question_id=question_id))
db.session.delete(question)
db.session.commit()
return redirect(url_for(('question._list')))
질문 수정 & 삭제 기능과 거의 비슷한 구성이지만 답변 등록 템플릿이 따로 없으므로 답변 수정에 사용할 템플릿이 추가로 필요하다.
question_detail.html의 답변 목록이 출력되는 부분에 답변 수정 버튼 추가
{% if g.user == answer.user %}
<div class="my-3">
<a href="{{ url_for('answer.modify', answer_id=answer.id) }}"
class="btn btn-sm btn-outline-secondary">수정</a>
</div>
answer_views.py 파일에 modify 함수 추가
from flask import Blueprint, url_for, request, render_template, g, flash
@bp.route('/modify/<int:answer_id>', methods=('GET', 'POST'))
@login_required
def modify(answer_id):
answer = Answer.query.get_or_404(answer_id)
if g.user != answer.user:
flash('수정권한이 없습니다')
return redirect(url_for('question.detail', question_id=answer.question.id))
if request.method == "POST":
form = AnswerForm()
if form.validate_on_submit():
form.populate_obj(answer)
answer.modify_date = datetime.now() # 수정일시 저장
db.session.commit()
return redirect(url_for('question.detail', question_id=answer.question.id))
else:
form = AnswerForm(obj=answer)
return render_template('answer/answer_form.html', answer=answer, form=form)
answer_form.html 파일 작성
{% extends 'base.html' %}
{% block content %}
<div class="container my-3">
<form method="post" class="post-form">
{{ form.csrf_token }}
{% include "form_errors.html" %}
<div class="form-group">
<label for="content">답변내용</label>
<textarea class="form-control" name="content" id="content"
rows="10">{{ form.content.data or '' }}</textarea>
</div>
<button type="submit" class="btn btn-primary">저장하기</button>
</form>
</div>
{% endblock %}
question_detail.html에 <삭제> 버튼 추가
<a href="#" class="delete btn btn-sm btn-outline-secondary "
data-uri="{{ url_for('answer.delete', answer_id=answer.id) }}">삭제</a>
answer_views.py 파일에 delete 함수 작성
@bp.route('/delete/<int:answer_id>')
@login_required
def delete(answer_id):
answer = Answer.query.get_or_404(answer_id)
question_id = answer.question.id
if g.user != answer.user:
flash('삭제권한이 없습니다')
else:
db.session.delete(answer)
db.session.commit()
return redirect(url_for('question.detail', question_id=question_id))
수정일시 표시
<div class="d-flex justify-content-end">
<!-- ------------------------------ [edit] -------------------------------- -->
{% if question.modify_date %}
<div class="badge badge-light p-2 text-left mx-3">
<div class="mb-2">modified at</div>
<div>{{ question.modify_date|datetime }}</div>
</div>
{% endif %}
<!-- ---------------------------------------------------------------------- -->
(... 생략 ...)
<div class="d-flex justify-content-end">
<!-- ------------------------------ [edit] -------------------------------- -->
{% if answer.modify_date %}
<div class="badge badge-light p-2 text-left mx-3">
<div class="mb-2">modified at</div>
<div>{{ answer.modify_date|datetime }}</div>
</div>
{% endif %}