[Flask] 모델로 데이터 처리하기 - 모델 사용하기

참조


모델 가져오기

  • 앞에서 생성한 모델들을 플라스크의 Migrate 기능이 인식할 수 있도록 pybo/init.py 파일을 다음과 같이 수정 합니다.
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy

import config

db = SQLAlchemy()
migrate = Migrate()

def create_app():
    app = Flask(__name__)
    app.config.from_object(config)

    # ORM
    db.init_app(app)
    migrate.init_app(app,db)
    from . import models

    # Blueprint
    from .views import main_views
    app.register_blueprint(main_views.bp)

    return app

데이터베이스 변경을 위한 리비전 파일 생성하기

  • 이제 명령 프롬프트에서 flask db migrate 명령을 수행합니다.
(myproject) C:\venvs\myproject>flask db migrate
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'question'
INFO  [alembic.autogenerate.compare] Detected added table 'answer'
Generating C:\venvs\myproject\migrations\versions\cc1a2433bfd0_.py ...  done
  • 이 명령을 수행하면 cc1a2433bfd0_.py 처럼 데이터베이스 변경 작업을 위한 리비전 파일이 생성됩니다.

    리비전(revision) 이란 생성된 cc1a2433bfd0_.py 파일명에서 cc1a2433bfd0_을 가리킵니다. 리비전은 flask db migrate 명령을 수행할 때 무작위로 만들어 집니다.


데이터베이스 갱신하기

  • 다음으로 flask db upgrade 명령으로 리비전 파일을 실행합니다.
(myproject) C:\venvs\myproject>flask db upgrade
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> cc1a2433bfd0, empty message
  • 이 과정에서 데이터베이스에 모델 이름과 똑같은 question과 answer 라는 이름의 테이블이 생성됩니다.
  • 지금까지의 동작이 정상 동작 되었으면, venvs/myproject 디렉터리에 pybo.db 파일이 생성되었습니다.
  • pybo.db 가 바로 SQLite 데이터베이스의 데이터 파일입니다.


플라스크 셸 실행하기

  • 플라스크 셸은 명령 프롬프트에서 flask shell 명령으로 실행합니다.
(myproject) C:\venvs\myproject>flask shell
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
App: pybo [development]
Instance: C:\venvs\myproject\var\pybo-instance
>>>

플라스크 셸은 프라스크를 실행하는 데 필요한 환경이 자동으로 설정되어 실행됩니다.


질문 데이터 저장하기

  • 다음 명령을 수행해 Question 과 Answer 모델을 플라스크 셸에 불러옵니다.
  • 그런 다음 Question 모델 객체를 하나 생성합니다.
>>> from pybo.models import Question, Answer
>>> from datetime import datetime
>>> q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=datetime.now())
  • Question 모델의 create_date 속성은 DateTime 유형이므로 datetiem.now 함수로 현재 일시를 대입했습니다.
  • 객체 q 를 만들었다고 해서 데이터베이스에 저장되는 것은 아닙니다.
  • 데이터베이스에 저장하려면 다음처럼 SQLAlchemy의 db 객체를 사용해야 합니다.
>>> from pybo import db
>>> db.session.add(q)
>>> db.session.commit()
  • 코드에서 보듯 신규 데이터를 저장할 떄는 add 함수를 사용한 다음 commit 함수까지 실행해야 합니다.
  • db.session은 데이터베이스와 연결된 세션, 즉 접속된 상태를 의미합니다.
  • 데이터베이스를 처리하려면 이 세션이 필요합니다.
  • 그리고 세션을 통해서 데이터를 저장, 수정, 삭제 작업을 한 다음에는 반드시 db.session.commit() 으로 커밋을 해줘야 합니다.
  • 데이터가 잘 생성되었는지 확인합니다.
>>> q.id
1
  • id는 Question 모델의 기본 키 입니다.
  • id는 앞서 모델을 생성할 때 설정했던 대로 데이터를 생성할 때 속성값이 자동으로 1씩 증가합니다.
  • 실제로 증가하는데 질문 데이터를 생성한 후, id 확인합니다.
>>> q = Question(subject='플라스크 모델 질문입니다.', content='id는 자동으로 생성되나요?', create_date=datetime.now())
>>> db.session.add(q)
>>> db.session.commit()
>>> q.id
2
  • id 가 2로 출력된 것을 확인할 수 있습니다.

데이터 조회하기

  • 이번에는 데이터베이스에 저장된 데이터를 조회해 봅니다.
>>> Question.query.all()
[<Question 1>, <Question 2>]
  • Question.query.all()로 데이터베이스에 저장된 질문 데이터를 전부 조회했습니다.
  • 이 함수는 Question 객체 리스트를 반환합니다.
  • 결과에서 보이는 숫자 1,2 는 Question 객체의 id 속성값입니다.
>>> Question.query.filter(Question.id==1).all()
[<Question 1>]
  • filter 함수는 인자로 전달한 조건에 맞는 데이터를 모두 반환해줍니다.
  • 여기서는 기본 키인 id를 이용했으므로 값을 1개만 반환합니다.
  • id는 유일한 값이므로 filter 함수 대신 get 함수를 이용해 조회할 수도 있습니다.
>>> Question.query.get(1)
<Question 1>
  • 다만 get 함수로 조회하면 리스트가 아닌 Question 객체 1개만 반환됩니다.

데이터 수정하기

  • 데이터를 수정할 떄는 단순히 대입 연산자를 사용하면 됩니다.
>>> 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>]

답변 데이터 생성 후 저장하기

  • 이번에는 답변(Answer) 데이터를 생성하고 저장합니다.
>>> from datetime import datetime
>>> from pybo.models import Question, Answer
>>> 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()
>>> a.id
1
>>> a = Answer.query.get(1)
>>> a
<Answer 1>

답변에 연결된 질문 찾기 vs 질문에 달린 답변 찾기

  • 앞에서 구성한 Answer 모델의 question 속성을 이용하면 "답변에 연결된 질문" 을 조회할 수 있습니다.
>>> a.question
<Question 2>
  • 답변에 연결된 질문 찾기는 Answer 모델에 question 속성이 정의되어 있어서 매우 쉽습니다.
  • Question 모델과 Answer 모델은 현재 현결된 상태이고, Answer 모델의 question 속성에 역참조 설정 backref=db.backref('answer_set') 을 적용했습니다.
>>> q.answer_set
[<Answer 1>]
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY