반응형

로그인, 로그아웃 기능을 만들었으니 누가 작성했는지 표시할 수 있게 됩니다.

그래서 Quesiton, Answer 모델을 수정하여 글쓴이에 해당하는 user 필드를 추가할 것입니다.

 

ORM을 사용할 때 몇 가지 문제점이 있습니다. SQLite 에서만 해당하고 다른 DB는 상관이 없습니다.

SQLite가 발생시킬 수 있는 오류를 먼저 해결하고 넘어가겠습니다.

(이럴 거면 그냥 다른 DB 쓰면 안 되나?) 

 

몇몇 데이터베이스의 제약 조건 이름이 변경되므로

flask db migrate, flask db upgrade로 데이터베이스를 변경해야 합니다..

 

from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData

import config

naming_convention ={
        "ix" : "ix_%(column_0_label)s",
        "uq" : "uq_%(table_name)s_%(column_0_name)s",
        "ck" : "ck_%(table_name)s_%(column_0_name)s",
        "fk" : "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        "pk" : "pk_%(table_name)s"
}
db = SQLAlchemy(metadata=MetaData(naming_convention=naming_convention))
migrate = Migrate()

def create_app():
        app = Flask(__name__)
        app.config.from_object(config) # config.py에 작성 내용을 환경 변수로 부르기 위한 작업

        # ORM
        db.init_app(app) # 우리가 적은 환경으로 DB 초기화
        if app.config['SQLALCHEMY_DATABASE_URI'].startswith("sqlite"):
                migrate.init_app(app, db, render_as_batch=True)  # DB와 우리가 적은 환경을 다른 환경으로 옮김
        else:
                migrate.init_app(app, db)
        from . import models

        # bluePrint
        from .views import main_views, question_views, answer_views, auth_views # .view에서 .은 현재위치의 views 폴더로부터 import한다는 말
        app.register_blueprint(main_views.bp) # 블루프린트 객체 bp 등록
        app.register_blueprint(question_views.bp) # 블루프린트 객체 bp 등록
        app.register_blueprint(answer_views.bp)
        app.register_blueprint(auth_views.bp)

        # 필터
        from .filter import format_datetime
        app.jinja_env.filters['datetime'] = format_datetime

        return app

SQLite 데이터베이스에서 사용하는 인덱스 등의 제약 조건 이름MetaData 클래스를 사용하여

규칙을 정의해야 합니다. 정의 하지 않으면 제약 조건에 이름이 없다는 오류 발생시킵니다.

 

render_as_batchTrue로 지정해야 합니다. False면 제약 조건 변경을 지원하지 않는다는 오류를 만듭니다.

 

이러한 과정들은 SQLite DB플라스크 ORM에서 정상 사용하기 위합니다.

자세한 과정은 몰라도 된다고 적혀있네요...

 

(제약조건 : Primary key 이런 걸 의미하는 것 같습니다.)

 

from pybo import db

class Question(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    subject = db.Column(db.String(200), nullable = False)
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
    user = db.relationship('User',backref=db.backref('question_set'))

class Answer(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete = 'cascade'))
    question = db.relationship('Question', backref=db.backref('answer_set', ))
    # question = db.relationship('Question', backref=db.backref('answer_set', casecade='all, delete-orphan'))
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)

class User(db.Model) :
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

일단 Question를 먼저 수정하겠습니다.

 

user_id User의 id값하고 값을 공유합니다.

userUser라는 테이블과 연결해 User테이블에 접근할 수 있게 만듭니다.

 

모델을 수정했으므로 flask db migrate 명령으로 리비전 파일을 생성합시다.

 

리비전 파일을 flask db upgrade 명령으로 적용하겠습니다.

오류가 발생합니다. 이유는 user_id 필드가 Null을 허용하지 않기 때문입니다.

앞서 실습진행하면서 데이터 여러 건 저장했습니다. 그 데이터에는 user_id 필드의 값이 없죠

(왜냐하면 지금 추가했으니깐요 예전 데이터의 값이 없겠죠 그래서 값이 들어가있지 않음)

근데 null 허용을 안 하니까 오류가 발생한 것입니다.

 

 

해결 하기 위한 5단계를 거쳐야 합니다.

 

1. user_id nullable 설정을 False 대신 True로 바꾸기

2. user_id를 임의 값으로 설정하기 (여기서는 1로 설정)

from pybo import db

class Question(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    subject = db.Column(db.String(200), nullable = False)
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=True, server_default='1')
    user = db.relationship('User',backref=db.backref('question_set'))

class Answer(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete = 'cascade'))
    question = db.relationship('Question', backref=db.backref('answer_set', ))
    # question = db.relationship('Question', backref=db.backref('answer_set', casecade='all, delete-orphan'))
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)

class User(db.Model) :
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

Question에 있는 user_id 부분 nullable을 바꾸고 server_defualt을 설정했습니다.

 

 

3. flask db migrate 명령, flask db upgrade 명령 다시 실행하기

이전 migrate 명령은 제대로 수행 되었지만 upgrade를 실패하여 정상 종료가 되었지 않기 때문입니다.

 

flask db heads로 최종 리비전을 확인해봅시다. (방금 적용시킨 거)

 

flask db current현재 작업 리비전(저번에 적용시킨 거)을 확인해 봅시다.

서로 같지 않아현재 리비전을 최종 리비전으로 변경해야 합니다.

 

flask db stamp heads이용해 바꿨고 flasdk db current로 제대로 바뀌었는지 확인 했습니다.

 

그러면 정상 종료된 것이기 때문에 다시 flask db migrate와 flask db upgrade를 해줍시다.

Question 모델 데이터 모든 user_id 필드에 1이 저장되었습니다.

 

4. user_id의 nullable 설정을 다시 False로 변경 (다시 원래 False로 변경)

5. flask db migrate 명령, flask db upgrade 명령 다시 실행

 

from pybo import db

class Question(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    subject = db.Column(db.String(200), nullable = False)
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullabe =False)
    user = db.relationship('User',backref=db.backref('question_set'))

class Answer(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete = 'cascade'))
    question = db.relationship('Question', backref=db.backref('answer_set', ))
    # question = db.relationship('Question', backref=db.backref('answer_set', casecade='all, delete-orphan'))
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)

class User(db.Model) :
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

Question 클래스를 수정flask db migrate, flask db upgrade 명령을 수행하겠습니다.

 

 

 

 

Answer 모델도 같은 방법으로 user_id 필드를 추가하겠습니다.

Question이랑 같은 방법으로 하시면 됩니다. 

 

from pybo import db

class Question(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    subject = db.Column(db.String(200), nullable = False)
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
    user = db.relationship('User',backref=db.backref('question_set'))

class Answer(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete = 'cascade'))
    question = db.relationship('Question', backref=db.backref('answer_set', ))
    # question = db.relationship('Question', backref=db.backref('answer_set', casecade='all, delete-orphan'))
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=True, server_default='1')
    user = db.relationship('User',backref=db.backref('answer_set'))

class User(db.Model) :
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

nullable = True 와 server_default = '1'을 수정하고 적용했습니다.

from pybo import db

class Question(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    subject = db.Column(db.String(200), nullable = False)
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
    user = db.relationship('User',backref=db.backref('question_set'))

class Answer(db.Model) :
    id = db.Column(db.Integer, primary_key = True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete = 'cascade'))
    question = db.relationship('Question', backref=db.backref('answer_set', ))
    # question = db.relationship('Question', backref=db.backref('answer_set', casecade='all, delete-orphan'))
    content = db.Column(db.Text(), nullable = False)
    create_date = db.Column(db.DateTime(), nullable = False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
    user = db.relationship('User',backref=db.backref('answer_set'))

class User(db.Model) :
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

nullable = False로 수정하고 적용했습니다.

 

from datetime import datetime

from flask import Blueprint, url_for, request, render_template, g
from werkzeug.utils import redirect

from .. import db
from ..models import Question, Answer
from ..forms import AnswerForm

bp = Blueprint('answer', __name__, url_prefix='/answer')

@bp.route('/create/<int:question_id>', methods=('POST', ))
def create(question_id):
    form = AnswerForm()
    question = Question.query.get_or_404(question_id) # 그 질문에 해당하는 번호를 가져온다.
    if form.validate_on_submit():
        content = request.form['content']  # name 속성이 content인 값
        answer = Answer(content=content, create_date=datetime.now(), user=g.user)  # textArea 내용, 작성시각, 작성자
        question.answer_set.append(answer)  # question.answer_set 은 Answer과 동일 즉, 거기에다가 값을 추가하는 것임
        db.session.commit()  # db에 저장
        return redirect(url_for('question.detail', question_id=question_id))  # 상세 질문과 답변이 있는 페이지로 전달
    return render_template('question/question_detail.html', question=question, form=form)

answer_views.py 입니다.

 

댓글 작성자가 필요하기 때문에 로그인 되어 있으면 g.user에 id가 저장되어 있으므로 그걸 user에다 저장합니다.

 

from datetime import datetime

from flask import Blueprint, render_template, request, url_for, g
from ..models import Question
from werkzeug.utils import redirect
from .. import db

from ..forms import QuestionForm, AnswerForm

bp = Blueprint('question', __name__, url_prefix='/question')

@bp.route('/list')
def _list():
    page = request.args.get('page', type=int, default=1) # 페이지
    question_list = Question.query.order_by(Question.create_date.desc())
    question_list = question_list.paginate(page, per_page=10)
    return render_template('question/question_list.html', question_list=question_list)

@bp.route('/detail/<int:question_id>')
def detail(question_id):
    form = AnswerForm()
    question = Question.query.get_or_404(question_id)
    return render_template('question/question_detail.html', question=question, form=form)

@bp.route('/create/', methods=('GET', 'POST'))
def create():
    form = QuestionForm()
    if request.method == 'POST' and form.validate_on_submit():
        question = Question(subject=form.subject.data, content=form.content.data, create_date=datetime.now(), user=g.user)
        db.session.add(question)
        db.session.commit()
        return redirect(url_for('main.index'))
    return render_template('question/question_form.html', form=form)

question_views.py 입니다.

 

글 작성자가 필요하기 때문에 로그인 되어 있으면 g.user에 id가 저장되어 있으므로 user에다 저장합니다.

 

 

로그아웃 상태에서 질문 또는 답변을 등록이 불가능하게 오류를 발생시켜보도록 하겠습니다.

 

@login_required 어노테이션을 지정하면 login_required 데코레이션 함수가 먼저 실행 됩니다.

(즉 def login_required(view)라는 것이 @login_required 과 똑같은 의미입니다.)

login_required 함수는 g.user가 있는지 조사하고 없으면 로그인 URL로 리다이렉트합니다.

g.user가 있으면 원래 함수를 그대로 실행합니다.

 

이런걸 데코레이터 함수라고 하는데 나중에 설명해서 올리도록 하겠습니다.

 

from datetime import datetime

from flask import Blueprint, url_for, request, render_template, g
from werkzeug.utils import redirect

from .auth_views import login_required
from .. import db
from ..models import Question, Answer
from ..forms import AnswerForm

bp = Blueprint('answer', __name__, url_prefix='/answer')

@bp.route('/create/<int:question_id>', methods=('POST', ))
@login_required
def create(question_id):
    form = AnswerForm()
    question = Question.query.get_or_404(question_id) # 그 질문에 해당하는 번호를 가져온다.
    if form.validate_on_submit():
        content = request.form['content']  # name 속성이 content인 값
        answer = Answer(content=content, create_date=datetime.now(), user=g.user)  # textArea 내용, 작성시각, 작성자
        question.answer_set.append(answer)  # question.answer_set 은 Answer과 동일 즉, 거기에다가 값을 추가하는 것임
        db.session.commit()  # db에 저장
        return redirect(url_for('question.detail', question_id=question_id))  # 상세 질문과 답변이 있는 페이지로 전달
    return render_template('question/question_detail.html', question=question, form=form)

answer_views.py 입니다

 

@login_required를 넣어서 로그인 라우트가 실행하기 전에 로그인 되어있는지 확인하는 것입니다.

 

from datetime import datetime

from flask import Blueprint, render_template, request, url_for, g

from .auth_views import login_required
from ..models import Question
from werkzeug.utils import redirect
from .. import db

from ..forms import QuestionForm, AnswerForm

bp = Blueprint('question', __name__, url_prefix='/question')

@bp.route('/list')
def _list():
    page = request.args.get('page', type=int, default=1) # 페이지
    question_list = Question.query.order_by(Question.create_date.desc())
    question_list = question_list.paginate(page, per_page=10)
    return render_template('question/question_list.html', question_list=question_list)

@bp.route('/detail/<int:question_id>')
def detail(question_id):
    form = AnswerForm()
    question = Question.query.get_or_404(question_id)
    return render_template('question/question_detail.html', question=question, form=form)

@bp.route('/create/', methods=('GET', 'POST'))
@login_required
def create():
    form = QuestionForm()
    if request.method == 'POST' and form.validate_on_submit():
        question = Question(subject=form.subject.data, content=form.content.data, create_date=datetime.now(), user=g.user)
        db.session.add(question)
        db.session.commit()
        return redirect(url_for('main.index'))
    return render_template('question/question_form.html', form=form)

question_views.py 입니다.

 

위와 동일합니다.

 

<!DOCTYPE html>
<html lang="en">


<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% extends 'base.html' %}
    {% block content %}

    <div class="container my-3">
        <h2 class="border-bottom py-2">{{ question.subject }}</h2>
        <div class="card my-3">
            <div class="card-body">
                <div class="card-text" style="white-space: pre-line;">{{ question.content }}</div>
            </div>
            <div class="d-flex justify-content-end">
                <span class="badge bg-light text-dark">
                    {{ question.create_date|datetime }}
                </span>
            </div>
        </div>


        <h5 class="border-bottom my-3 py-2">{{ question.answer_set|length }}개의 답변이 있습니다.</h5>
        {% for answer in question.answer_set %}
        <div class="card my-3">
            <div class="card-body">
                <div class="card-text" style="white-space : pre-line;">
                    {{ answer.content }}
                </div>
                <div class="d-flex justify-content-end">
                    <span class="badge bg-light text-dark">
                        {{ answer.create_date|datetime }}
                    </span>
                </div>
            </div>
        </div>
        {% endfor %}

        <h5> {{ question.answer_set|length }}개의 답변이 있습니다. </h5>

        <div>
            <ul>
                {% for answer in question.answer_set %}
                    <li> {{ answer.content }}</li>
                {% endfor %}
            </ul>
        </div>

        <form class="my-3" action="{{ url_for('answer.create', question_id=question.id) }}" method="post">
          {{ form.csrf_token }}
          <!-- 오류표시 Start -->
          {% for field, errors in form.errors.items() %}
              <div class="alert alert-danger" role="alert">
                  <strong>{{ form[field].label }}</strong>: {{ ','.join(errors) }}
              </div>
          {% endfor %}
          <!-- 오류표시 End -->
            <div class="form-group">
                <textarea {% if not g.user %} disabled {% endif %} name="content" id="content" row="15"></textarea>
                <input class="btn btn-primary" type="submit" value="답변등록">
            </div>
        </form>
    </div>

    {% endblock %}
</body>
</html>

 

question_detail.html 입니다.

 

<textarea {% if not g.user %} disabled {% endif %} name="content" ....

이 부분을 이용해 아예 로그인이 되어있지 않을 때 입력조차 불가능하게 만들었습니다.

 

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% extends 'base.html' %}
    {% block content %}

    <div class="container my-3">
        <table calss="table" width="100%">
            <thead >
                <tr class="bg-dark text-white text-center">
                        <th> 번호 </th>
                        <th style="width:50%"> 제목 </th>
                        <th> 글쓴이 </th>
                        <th> 작성일시 </th>
                </tr>
            </thead>

            <tbody>
                {% if question_list %}
                {% for question in question_list.items %}
                <tr class="text-center">
                        <td>{{ question_list.total - ((question_list.page-1) * question_list.per_page) - loop.index0 }}</td>
                        <td class="text-start">
                            <a href="{{ url_for('question.detail', question_id=question.id) }}">{{question.subject}}</a>
                            {% if question.answer_set|length > 0 %}
                                <span class="text-danger small">{{ question.answer_set|length }}</span>
                            {% endif %}
                        </td>
                        <td>{{ question.user.username }}</td>
                        <td>{{ question.create_date|datetime  }}</td>
                </tr>
                {% endfor %}
                {% else %}
                <tr>
                    <td colspan="3"> 질문이 없습니다. </td>
                </tr>
                {% endif %}
            </tbody>
        </table>
        <!-- 페이징 -->
        <nav aria-label="Page navigation example">
          <ul class="pagination pagination-sm my-5 justify-content-center">
              <!-- 이전 페이징 구현 (이전 페이지 있을시)-->
              {% if question_list.has_prev %}
                <li class="page-item">
                    <a class="page-link" href="?page={{ question_list.prev_num }}">이전</a>
                </li>
              <!-- 이전 페이지가 없을 시 -->
              {% else %}
                <li class="page-item disabled">
                    <a class="page-link" href="">이전</a>
                </li>
              {% endif %}
              <!-- 중간 페이징 -->
              {% for page_num in question_list.iter_pages() %}
                {% if page_num %}
                    {% if page_num != question_list.page %}
                        <li class="page-item">
                            <a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a>
                        </li>
                    {% else %}
                        <li class="page-item active" aria-current="page">
                            <a class="page-link" href="#">{{ page_num }}</a>
                        </li>
                    {% endif %}
                {% else %}
                    <li class="disabled">
                        <a class="page-link" href="#">...</a>
                    </li>
                {% endif %}
              {% endfor %}
              <!-- 다음 페이징 구현 (다음 페이지가 있는 경우_ -->
              {% if question_list.has_next %}
                  <li class="page-item">
                      <a class="page-link" href="?page={{ question_list.next_num }}">다음</a>
                  </li>
              <!-- 다음 페이지 없는 경우 -->
              {% else %}
                  <li class="page-item disabled">
                      <a class="page-link" tabindex="-1" aria-disabled="true" href="#">다음</a>
                  </li>
              {% endif %}
          </ul>
        </nav>

        </ul>
        <a href="{{ url_for('question.create') }}" class="btn btn-primary"> 질문 등록하기 </a>
    </div>

    {% endblock %}

</body>
</html>

question_list.html 입니다.

 

이제 유저값이 들어갔으므로 글쓴이와 댓글 작성자를 표시하겠습니다.

중요한 부분은 {{ question.user.username }} 입니다.

 

 

DB객체에 접근하는 법에 대해서 다시 정리해보겠습니다.

question.answer_set 으로 Answer 객체에 접근 가능합니다. (<Answer[1]> <Answer[2]>....)

Answer에서 선언해야 접근가능합니다 (question = db.relationship('Question', backref=db.backref('answer_set', )))

하지만 내부는 불가능 합니다. (question.answer_set이 Answer[1]이지만 question.answer_set.id 불가능)

 

question.클래스속성으로 Question 객체 클래스 속성 접근 가능합니다. ( {{ question.id }} )

 

user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)

User.id값하고 Question의 user_id하고 똑같은 값을 가지게 됩니다.

 

relationship(테이블명, back? 이건 모르겠음) 조사해야합니다....

user = db.relationship('User',backref=db.backref('question_set'))

이걸로는 해당 user_id에 해당하는 모든 user 속성에 접근 가능하게 만듭니다.
question.user.username 이렇게 접근할 수 있게 하는 것이죠

<!DOCTYPE html>
<html lang="en">


<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% extends 'base.html' %}
    {% block content %}

    <div class="container my-3">
        <h2 class="border-bottom py-2">{{ question.subject }}</h2>
        <div class="card my-3">
            <div class="card-body">
                <div class="card-text" style="white-space: pre-line;">{{ question.content }}</div>
            </div>
            <div class="d-flex justify-content-end">
                <span class="badge bg-light text-dark text-left">
                    <span class="mb-2"> {{ question.user.username }} </span>
                    <span> {{ question.create_date|datetime }} </span>
                </span>
            </div>
        </div>


        <h5 class="border-bottom my-3">{{ question.answer_set|length }}개의 답변이 있습니다.</h5>
        {% for answer in question.answer_set %}
        <div class="card my-3">
            <div class="card-body">
                <div class="card-text" style="white-space : pre-line;">
                    {{ answer.content }}
                </div>
            </div>
            <div class="d-flex justify-content-end">
                <span class="badge bg-light text-dark text-left">
                    <span class="mb-2"> {{ answer.user.username }}  </span>
                    <span> {{ answer.create_date|datetime }} </span>
                </span>
            </div>
        </div>
        {% endfor %}

        <h5> {{ question.answer_set|length }}개의 답변이 있습니다. </h5>

        <div>
            <ul>
                {% for answer in question.answer_set %}
                    <li> {{ answer.content }}</li>
                {% endfor %}
            </ul>
        </div>

        <form class="my-3" action="{{ url_for('answer.create', question_id=question.id) }}" method="post">
          {{ form.csrf_token }}
          <!-- 오류표시 Start -->
          {% for field, errors in form.errors.items() %}
              <div class="alert alert-danger" role="alert">
                  <strong>{{ form[field].label }}</strong>: {{ ','.join(errors) }}
              </div>
          {% endfor %}
          <!-- 오류표시 End -->
            <div class="form-group">
                <textarea {% if not g.user %} disabled {% endif %} name="content" id="content" row="15"></textarea>
                <input class="btn btn-primary" type="submit" value="답변등록">
            </div>
        </form>
    </div>

    {% endblock %}
</body>
</html>

question_detail.html 입니다.

 

게시글 작성 시각과 댓글 작성 시각을 추가시켰습니다.

 

반응형