Flask 모델 만들기
질문 답변 게시판 예제
- 모델 속성 구상하기
질문 모델
속성명 | 설명 |
---|---|
id | 질문 데이터의 고유 번호 |
subject | 질문 제목 |
content | 질문 내용 |
create_date | 질문 작성일시 |
답변 모델
속성명 | 설명 |
---|---|
id | 질문 데이터의 고유 번호 |
question_id | 질문 데이터의 고유 번호 |
content | 답변 내용 |
create_date | 답변 작성일시 |
- 질문 모델 생성하기
# projects > firstproject > pybo > models.py
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)
- 답변 모델 생성하기
# projects > firstproject > pybo > models.py
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',))
content = db.Column(db.Text(), nullable=False)
create_date = db.Column(db.DateTime(), nullable=False)
db.ForeignKey에 지정한 첫 번째 값은 연결할 모델의 속성명이고 두 번째 ondelete에 지정한 값은 삭제 연동 설정이다. 즉, 답변 모델의 question_id 속성은 질문 모델의 id 속성과 연결되며 ondelete=’CASCADE’에 의해 데이터베이스에서 쿼리를 이용하여 질문을 삭제하면 해당 질문에 달리 답변도 함께 삭제된다.
question 속성은 답변 모델에서 질문 모델을 참조하려고 추가했다. 예를 들어 답변 모델 객체에서 질문 모델 객체의 제목을 참조한다면 answer.question,subject 처럼 할 수 있다. 이렇게 하려면 속성을 추가할 때 db.Column 이 아닌 db.relationship을 사용해야 한다.
db.relationship에 지정한 첫 번째 값은 참조할 모델이고, 두 번째 backref에 지정한 값은 역참조 설정이다. 역참조란 질무에서 답변을 참조하는 것을 의미한다. 한 질문에는 여러 개의 답변이 달릴 수 있는데 역참조는 이 질문에 달린 답변을 참조할 수 있게 한다. 예를 들어 어떤 질문에 해당하는 객체가 a_question이라면 a_question.answer_set와 같은 코드로 해당 질문에 달린 답변을 참조할 수 있다.
파이썬 코드 a_question.delete()로 질문 데이터를 삭제하면 해당 질문과 연관된 답변 데이터는 삭제되지 않고 답변 데이터의 question_id 컬럼만 빈값으로 업데이트 된다. 만약 파이썬 코드로 질문 데이터를 삭제할 때 연관된 답변 데이터가 모두 삭제되기를 바란다면 db.backref 설정에 cascade=’all, delete-orphan’ 옵션을 추가해야 한다.
모델을 이용해 테이블 자동 생성
- 모델 가져오기
# pybo > __init__.py
...
# ORM
db.init_app(app)
migrate.init_app(app, db)
from . import models
...
- 데이터베이스 변경을 위한 리비전 파일 생성
Question과 Answer 모델을 추가했으므로 데이터베이스가 변경되도록 명력 프롬프트에서 flask db migrate 명령을 수행
flask db migrate
- 데이터베이스 갱신
리비전 파일을 아래 명령어로 실행할 수 잇다. 이 때 데이터베이스에 모델 이름과 똑같은 question과 answer 라는 이름의 테이블이 생성된다. pybo.db가 SQLite 데이터베이스의 데이터 파일 이다.
flask db upgrade
- SQLite 확인
vscode 마켓에 SQLite viewer 를 활용하여 pybo.db를 접근하면 쉽게 볼 수 있다.
모델 사용하기
- 프라스크 셸 실행
flask shell
- 질문 데이터 저장하기
from pybo.models import Question, Answer
from datetime import datetime
q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=datetime.now())
from pybo import db
db.session.add(q)
db.session.commit()
q.id # AutoIncrease
# 1
db.session.rollback 함수로 데이터 되돌리기가 가능
q = Question(subject='플라스크 모델 질문입니다.', content='id는 자동으로 생성되나요?', create_date=datetime.now())
db.session.add(q)
db.session.commit()
- 데이터 조회하기
Question.query.all()
# [<Question 1>, <Question 2>]
# filter 함수는 인자로 전달한 조건에 맞는 데이터를 모두 반환해 준다.
Question.query.filter(Question.id==1).all()
# [<Question 1>]
# get 함수로 조회하면 리스트가 아닌 Quetion 객체 1개만 반환된다.
Question.query.get(1)
# <Question 1>
# filter와 like를 활용한 조회
Question.query.filter(Question.subject.like('%플라스크%')).all()
# [<Question 2>]
- 데이터 수정
q = Question.query.get(2)
q
# <Question 2>
q.subject = 'Flask Model Question'
db.session.commit()
- 데이터 삭제
q = Question.query.get(1)
db.session.delete(q)
db.session.commit()
Question.query.all()
# [<Question 2>]
- 답변 데이터 생성 후 저장하기
from pybo.models import Question, Answer
from datetime import datetime
from pybo import db
q = Question.query.get(2)
a = Answer(question=q, content='네 자동으로 생성됩니다.', create_date=datetime.now())
db.session.add(a)
db.session.commit()
id가 2인 질문 데이터를 가져온 다음 q에 저장했다. 그 런 다음 Answer 모델의 question 속성에 방금 가져온 q를 대입해 답변 데이터를 생성했다.
- 답변에 연결된 질문 찾기 vs 질문에 달린 답변 찾기
# 답변에 연결된 질문 찾기
a.question
# 질문에 달린 답변 찾기
# backref=db.backref('answer_set')
q.answer_set