게시물 수정 & 삭제 기능

jurin·2020년 12월 29일
0

플라스크 - python

목록 보기
16/17

책 '점프 투 플라스크'를 공부하면서 정리한 내용입니다.
출처 : https://wikidocs.net/81060

모델 수정

Question, Answer 모델에 modify_date 필드 추가

modify_date = db.Column(db.DateTime(), nullable=True)

수정일시는 수정이 발생할 경우에만 생성하므로 null을 허용하도록 했다.

모델이 변경되었으므로 migrate, upgrade 명령을 수행한다.

질문 수정 기능 추가

1. 질문 수정 버튼 추가

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 %}와 같이 추가한다.

2. 질문 수정 라우트 함수 modify

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 객체에 적용

질문 삭제 기능

1. 질문 삭제 버튼 추가

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 속성도 추가

2. 질문 삭제 버튼에 jQuery 사용

<삭제> 버튼을 구현할 때 ‘정말로 삭제하시겠습니까?’와 같은 확인 창 띄우기

<삭제>버튼을 누르면 확인 창이 나타나고, 확인 창에서 <확인> 버튼을 누르면 앞서 입력했던 data-uri 속성값으로 URL 호출이 실행

3. jQuery 실행을 위해 base.html 파일 수정

base.html 파일에 jQuery 로드 관련 코드가 추가되어 있기 때문에 base.html 파일을 수정한다.

<!-- 자바스크립트 Start -->
{% block script %}
{% endblock %}
<!-- 자바스크립트 End -->

4. 삭제 알림 창 기능 추가

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>

5. 질문 삭제 라우트 함수 delete 추가

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')))

답변 수정 & 삭제 기능

질문 수정 & 삭제 기능과 거의 비슷한 구성이지만 답변 등록 템플릿이 따로 없으므로 답변 수정에 사용할 템플릿이 추가로 필요하다.

1. 답변 수정 버튼 추가

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>

2. 답변 수정 라우트 함수 modify

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)

3. 답변 수정 폼 작성

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 %}

4. 답변 삭제 버튼 추가

question_detail.html에 <삭제> 버튼 추가

<a href="#" class="delete btn btn-sm btn-outline-secondary "
                data-uri="{{ url_for('answer.delete', answer_id=answer.id) }}">삭제</a>

5. 답변 삭제 함수

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 %}
profile
anaooauc1236@naver.com

0개의 댓글

관련 채용 정보