댓글 기능 추가
책 '점프 투 플라스크'를 공부하면서 정리한 내용입니다.
출처 : https://wikidocs.net/81060
댓글에 사용할 모델 생성
Comment 모델 생성
class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
user = db.relationship('User', backref=db.backref('comment_set'))
content = db.Column(db.Text(), nullable=False)
create_date = db.Column(db.DateTime(), nullable=False)
modify_date = db.Column(db.DateTime())
question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete='CASCADE'), nullable=True)
question = db.relationship('Question', backref=db.backref('comment_set'))
answer_id = db.Column(db.Integer, db.ForeignKey('answer.id', ondelete='CASCADE'), nullable=True)
answer = db.relationship('Answer', backref=db.backref('comment_set'))
질문 or 답변을 DB에서 삭제하면 연관된 댓글도 삭제될 수 있도록 ondelete='CASCADE' 옵션 설정
question_id 필드, answer_id 필드 중 하나에만 값이 저장되므로 두 필드는 모두 nullable=True여야 한다.
모델을 수정했으니 migrate, upgrade 명령 수행
질문 댓글 기능 추가
1. 댓글 목록, 댓글 입력 링크 추가
question_detail.html
<!-- 질문 댓글 Start -->
{% if question.comment_set|length > 0 %}
<div class="mt-3">
{% for comment in question.comment_set %}
<div class="comment py-2 text-muted">
<span style="white-space: pre-line;">{{ comment.content }}</span>
<span>
- {{ comment.user.username }}, {{ comment.create_date|datetime }}
{% if comment.modify_date %}
(수정:{{ comment.modify_date|datetime }})
{% endif %}
</span>
{% if g.user == comment.user %}
<a href="{{ url_for('comment.modify_question', comment_id=comment.id) }}" class="small">수정</a>,
<a href="#" class="small delete"
data-uri="{{ url_for('comment.delete_question', comment_id=comment.id) }}">삭제</a>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
<div>
<a href="{{ url_for('comment.create_question', question_id=question.id) }}"
class="small"><small>댓글 추가 ..</small></a>
</div>
<!-- 질문 댓글 End -->
2. comment 클래스 CSS
comment 클래스는 댓글을 작게 보여 주는 클래스로 CSS를 별도 작성해야 함
댓글마다 상단에 점선 추가, 글꼴 크기 0.7em 설정
.comment {
border-top:dotted 1px #ddd;
font-size:0.7em;
}
3. 질문 댓글 폼 작성
forms.py 파일에 댓글 등록 시 사용할 CommentForm 클래스 추가
class CommentForm(FlaskForm):
content = TextAreaField('내용', validators=[DataRequired()])
4. 질문 댓글 등록 함수 생성
comment_views.py 생성
질문 상세 템플릿의 댓글추가 링크에 해당하는 create_question 함수 작성
from datetime import datetime
from flask import Blueprint, url_for, request, render_template, g
from werkzeug.utils import redirect
from pybo import db
from pybo.forms import CommentForm
from pybo.models import Question, Comment
from pybo.views.auth_views import login_required
bp = Blueprint('comment', __name__, url_prefix='/comment')
@bp.route('/create/question/<int:question_id>', methods=('GET', 'POST'))
@login_required
def create_question(question_id):
form = CommentForm()
question = Question.query.get_or_404(question_id)
if request.method == 'POST' and form.validate_on_submit():
comment = Comment(user=g.user, content=form.content.data, create_date=datetime.now(), question=question)
db.session.add(comment)
db.session.commit()
return redirect(url_for('question.detail', question_id=question_id))
return render_template('comment/comment_form.html', form=form)
질문에 달린 댓글이니까 Comment 모델 객체를 생성할 때 question 필드에 값을 설정했다.
5. 블루프린트 추가
comment_views.py 파일에 블루프린트를 추가했으니까 __init__.py 파일에도 블루프린트를 등록해줘야 한다.
from .views import main_views, question_views, answer_views, auth_views, comment_views
app.register_blueprint(comment_views.bp)
6. 질문 댓글 템플릿 작성
comment_form.html 템플릿 작성
{% extends 'base.html' %}
{% block content %}
<div class="container my-3">
<h5 class="border-bottom pb-2">댓글등록하기</h5>
<form method="post" class="post-form my-3">
{{ form.csrf_token }}
{% include "form_errors.html" %}
<div class="form-group">
<label for="content">댓글내용</label>
<textarea class="form-control" name="content" id="content"
rows="3">{{ form.content.data or '' }}</textarea>
</div>
<button type="submit" class="btn btn-primary">저장하기</button>
</form>
</div>
{% endblock %}
7. 질문 댓글 수정 함수
댓글 수정을 위해 comment_views.py에서 modify_question 함수 작성
from flask import Blueprint, url_for, request, render_template, g, flash
@bp.route('/modify/question/<int:comment_id>', methods=('GET', 'POST'))
@login_required
def modify_question(comment_id):
comment = Comment.query.get_or_404(comment_id)
if g.user != comment.user:
flash('수정권한이 없습니다')
return redirect(url_for('question.detail', question_id=comment.question.id))
if request.method == 'POST':
form = CommentForm()
if form.validate_on_submit():
form.populate_obj(comment)
comment.modify_date = datetime.now() # 수정일시 저장
db.session.commit()
return redirect(url_for('question.detail', question_id=comment.question.id))
else:
form = CommentForm(obj=comment)
return render_template('comment/comment_form.html', form=form)
8. 질문 댓글 삭제 함수
comment_views.py에 delete_question 함수 작성
@bp.route('/delete/question/<int:comment_id>')
@login_required
def delete_question(comment_id):
comment = Comment.query.get_or_404(comment_id)
question_id = comment.question.id
if g.user != comment.user:
flash('삭제권한이 없습니다')
return redirect(url_for('question.detail', question_id=question_id))
db.session.delete(comment)
db.session.commit()
return redirect(url_for('question.detail', question_id=question_id))
답변 댓글 기능
1. 답변 댓글 목록과 댓글 입력 링크 추가
question_detail.html
<!-- 답변 댓글 Start -->
{% if answer.comment_set|length > 0 %}
<div class="mt-3">
{% for comment in answer.comment_set %}
<div class="comment py-2 text-muted">
<span style="white-space: pre-line;">{{ comment.content }}</span>
<span>
- {{ comment.user.username }}, {{ comment.create_date|datetime }}
{% if comment.modify_date %}
(수정:{{ comment.modify_date|datetime }})
{% endif %}
</span>
{% if g.user == comment.user %}
<a href="{{ url_for('comment.modify_answer', comment_id=comment.id) }}" class="small">수정</a>,
<a href="#" class="small delete"
data-uri="{{ url_for('comment.delete_answer', comment_id=comment.id) }}">삭제</a>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
<div>
<a href="{{ url_for('comment.create_answer', answer_id=answer.id) }}"
class="small"><small>댓글 추가 ..</small></a>
</div>
<!-- 답변 댓글 End -->
2. 답변 댓글 등록, 수정, 삭제 함수
comment_views.py
from pybo.models import Question, Comment, Answer
@bp.route('/create/answer/<int:answer_id>', methods=('GET', 'POST'))
@login_required
def create_answer(answer_id):
form = CommentForm()
answer = Answer.query.get_or_404(answer_id)
if request.method == 'POST' and form.validate_on_submit():
comment = Comment(user=g.user, content=form.content.data, create_date=datetime.now(), answer=answer)
db.session.add(comment)
db.session.commit()
return redirect(url_for('question.detail', question_id=answer.question.id))
return render_template('comment/comment_form.html', form=form)
@bp.route('/modify/answer/<int:comment_id>', methods=('GET', 'POST'))
@login_required
def modify_answer(comment_id):
comment = Comment.query.get_or_404(comment_id)
if g.user != comment.user:
flash('수정권한이 없습니다')
return redirect(url_for('question.detail', question_id=comment.answer.id))
if request.method == 'POST':
form = CommentForm()
if form.validate_on_submit():
form.populate_obj(comment)
comment.modify_date = datetime.now() # 수정일시 저장
db.session.commit()
return redirect(url_for('question.detail', question_id=comment.answer.question.id))
else:
form = CommentForm(obj=comment)
return render_template('comment/comment_form.html', form=form)
@bp.route('/delete/answer/<int:comment_id>')
@login_required
def delete_answer(comment_id):
comment = Comment.query.get_or_404(comment_id)
question_id = comment.answer.question.id
if g.user != comment.user:
flash('삭제권한이 없습니다')
return redirect(url_for('question.detail', question_id=question_id))
db.session.delete(comment)
db.session.commit()
return redirect(url_for('question.detail', question_id=question_id))
Author And Source
이 문제에 관하여(댓글 기능 추가), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jusung-c/댓글-기능-추가저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)