플라스크 개발 기초 - 3

jurin·2020년 12월 5일
0

플라스크 - python

목록 보기
4/17

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

답변 데이터 저장하고 표시하기

답변을 입력하기 위한 텍스트 창(extarea)과 <답변등록> 버튼을 생성. 버튼을 누르면 텍스트 창에 입력된 데이터가 저장되도록 구현

  1. 답변 등록 버튼

질문 상세 조회 템플릿 파일(question_detail.html)에 form, textarea, input 엘리먼트 추가

<form action="{{ url_for('answer.create', question_id=question.id) }}" method="post">
    <textarea name="content" id="content" rows="15"></textarea>
    <input type="submit" value="답변등록">
</form>

답변 저장 URL은 form 엘리먼트 action 속성에 지정된 url_for('answer.create', question_id=question.id)함수가 알려준다. <답변등록> 버튼을 누르면 POST 방식으로 form 엘리먼트의 action 속성에 등록된 URL이 호출된다.

이제 답변 모델에 해당하는 블루프린트 파일을 작성하고 create 함수를 만들어야 한다.

  1. 답변 블루프린트

앞에서 질문 모델 question을 관리하는 블루프린트를 만든 것과 같이 답변 모델 answer을 관리하는 블루프린트를 만든다. views 디렉토리에 answer_wiews.py 파일을 만든다.

from datetime import datetime

from flask import Blueprint, url_for, request
from werkzeug import redirect

from pybo import db
from pybo.models import Question, Answer

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

@bp.route('/create/<int:question_id>', method=('Post',))
def create(question_id): # 매개변수 question_id는 URL에서 전달된다.
    question = Question.query.get_or_404(question_id)

    # form 엘리먼트를 통해 전달된 데이터들은 create 함수에서 request 객체로 얻을 수 있다.
    # POST 폼 방식으로 전송된 데이터 항목 중 name 속성이 'content'인 값을 의미한다.
    content = request.form['content']

    answer = Answer(content=content, create_date=datetime.now())

    question.answer_set.append(answer) # ‘질문에 달린 답변들’을 의미
    # Question과 Answer 모델이 연결되어 backref에 설정한 answer_set을 사용할 수 있다.

    db.session.commit()

    # 답변을 생성한 후 화면을 이동하도록 redirect 함수를 사용
    return redirect(url_for('question.detail', question_id=question_id))
    # question_id는 question_views.py 파일에 있는 detail 함수의 매개변수로 전달

create 함수의 매개변수 question_id는 URL에서 전달되기 때문에locahost:5000/answer/create/2/ 페이지를 요청받으면 question_id에는 2가 넘어온다.

@bp.route의 methods 속성에 'POST'를 지정했다. 앞서 작성한 답변 저장 템플릿의 form 엘리먼트가 POST 방식이었으니까 같은 값을 지정해야 한다. 같은 값을 지정하지 않는 경우 Method Not Allowed 오류가 발생한다.

methods 속성은 웹 브라우저에서 요청하는 GET 또는 POST와 같은 폼 방식을 의미한다.

form 엘리먼트를 통해 전달된 데이터들은 create 함수에서 request 객체로 얻을 수 있다. request.form['content'] 코드는 POST 폼 방식으로 전송된 데이터 항목 중 name 속성이 'content'인 값을 의미

답변을 저장하는 방법은 한 가지?
no. Answer 모델을 직접 사용해도 답변 저장 가능

answer = Answer(question=question, content=content, create_date=datetime.now())
db.session.add(answer)

request 객체란?
request 객체는 플라스크에서 생성 과정 없이 사용할 수 있는 기본 객체. 브라우저의 요청부터 응답까지 처리 구간에서 request 객체를 생성하여 사용할 수 있게 해준다. 이 객체를 이용해 브라우저에서 요청한 정보를 확인할 수 있다.

GET
GET 메소드는 주로 데이터를 읽거나(Read) 검색(Retrieve)할 때에 사용되는 메소드이다. 만약에 GET요청이 성공적으로 이루어진다면 XML이나 JSON과 함께 200 (Ok) HTTP 응답 코드를 리턴한다. 에러가 발생하면 주로 404 (Not found) 에러나 400 (Bad request) 에러가 발생한다.

POST
POST 메소드는 주로 새로운 리소스를 생성(create)할 때 사용된다. 조금 더 구체적으로 POST는 하위 리소스(부모 리소스의 하위 리소스)들을 생성하는데 사용된다. 성공적으로 creation을 완료하면 201 (Created) HTTP 응답을 반환한다.

GET vs POST
만약에 GET 메소드를 사용하면 모든 form data는 URL로 인코딩되어 action URL에 query string parameters로 전달된다. POST 메소드를 사용하면 form data는 HTTP request의 message body에 나타날 것이다.

출처: https://im-developer.tistory.com/166 [Code Playground]

  1. 답변 블루프린트 적용하기

앞서 생성한 블루프린트 객체 answer_views.bp를 pybo/__init__.py 파일에 등록

(...생략...)

def create_app():
    (...생략...)

    # 블루프린트
    from .views import main_views, question_views, answer_views
    app.register_blueprint(main_views.bp)
    app.register_blueprint(question_views.bp)
    app.register_blueprint(answer_views.bp)

    return app

질문 상세 조회 페이지를 접속해보면 답변을 등록할 수 있는 창과 버튼이 보인다.

  1. 질문 상세 페이지에 답변 표시하기

답변을 질문과 함께 보여야 하므로 질문 상세 조회 템플릿 파일을 수정한다.

<h5>{{ question.answer_set|length }}개의 답변이 있습니다.</h5>
<div>
    <ul>
    {% for answer in question.answer_set %}
        <li>{{ answer.content }}</li>
    {% endfor %}
    </ul>
</div>

답변을 확인할 수 있는 영역을 추가했다. length는 템플릿 필터인데 객체의 길이를 반환해준다. 필터는 |문자 뒤에 추가해서 사용한다.

profile
anaooauc1236@naver.com

0개의 댓글