flask - ohsangwon777/flask-sqlalchemy-test GitHub Wiki
๋ชจ๋ธ์ ์ํ๊ฐ๋ค
๋ชจ๋ธ์ ์ฌ๋ฌ ์ํ๊ฐ์ ๊ฐ์ง๋ฉฐ session์์ add, commit, delete, flush ๋ฑ์ด ๋ฐ์ํ๋ ์ํ๊ฐ์ด ๋ฐ๋๋ค.
transient
: ์ธ์ ์ ์ถ๊ฐ๋์ง ์์ ๋ชจ๋ธ์ ์ํ. ModelClass(name='aaa')๋ฑ์ผ๋ก ์์ฑ๋ง ํด๋์๊ฑฐ๋, session์์ ์ ๊ฑฐ๋์์ ๊ฒฝ์ฐ
pending
: session.add()๋ก ์ธ์
์ ์ถ๊ฐ ์์ ์ธ ๋ชจ๋ธ์ด ๊ฐ์ง๋ ์ํ. session.flush()๋ฅผ ํ๊ฒ๋๋ฉด persistent์ํ๋ก ๋ฐ๋๋ค.
persistent
: ์ธ์
์๋ ์กด์ฌํ๊ณ , ์ค์ ๋ก ๋ฐ์ดํฐ ๋ฒ ์ด์ค์๋ ์กด์ฌํ๋ ๋ชจ๋ธ์ด ๊ฐ์ง๋ ์ํ. pending์ํ ๋ชจ๋ธ์ด flush๋๊ฑฐ๋, ๋ฐ์ดํฐ ๋ฒ ์ด์ค์์ ์ฟผ๋ฆฌ๋ก ์กฐํํด์จ ๊ฒฝ์ฐ
detached
: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์๋ ์กด์ฌํ์ง๋ง ์ธ์
์๋ ์กด์ฌํ์ง ์๋ ์ํ. ์ถ๊ฐ๋ก ์ฟผ๋ฆฌ๋ฅผ ์คํ ์ํฌ ์ ์๋ค.
expired
: session.commit()์ด ์คํ๋ ํ ์ธ์
์ ์๋ persistent์ํ ๋ชจ๋ธ๋ค์ด ๊ฐ์ง๋ ์ํ. expired๋ก ๋งํน๋๋ฉด ์๋ก์ด ๊ฐ์ ์กฐํํ๊ฒ ๋๋ค. expire_on_commit=False
์ผ๋ก ์ค์ ํ ์ ์๋ค.(ํ ...)
scoped_session
@db_test_api.route('/request_1')
class Request_1(Resource):
def get(self):
logger.info('request_1 session : {}'.format(db.session))
logger.info('request_1 session.identity_map: {}'.format(db.session.identity_map))
return 200
@db_test_api.route('/request_2')
class Request_2(Resource):
def get(self):
logger.info('request_2 session : {}'.format(db.session))
logger.info('request_2 session.identity_map: {}'.format(db.session.identity_map))
return 200
[INFO] request_1 session : <sqlalchemy.orm.scoping.scoped_session object at 0x05AD3630>
[INFO] request_2 session : <sqlalchemy.orm.scoping.scoped_session object at 0x05AD3630>
[INFO] request_1 session.identity_map: <sqlalchemy.orm.identity.WeakInstanceDict object at 0x065C8090>
[INFO] request_2 session.identity_map: <sqlalchemy.orm.identity.WeakInstanceDict object at 0x065ACFB0>
flask-sqlalchemy ์ด๊ธฐํ ๋ ๋ scoped_session
์ ํ๋ ์์ฑํด์ ์ธํ
ํด์ค๋ค.
๊ฐ ๋ฆฌํ์คํธ๋ณ๋ก session๊ฐ์ฒด๋ ๊ฐ๋ค.
ํ์ง๋ง ๊ฐ ๋ฆฌํ์คํธ์์ ์กฐํํ๋ session๊ฐ์ฒด๋ค์ _app_ctx_stack.__ident_func__
๋ก ๊ตฌ๋ถ๋์ด ๊ฐ๊ฐ ๋ค๋ฅธ scope๋ฅผ ๊ฐ์ง๋ค.
session์ identity_map
์ persist ์ํ์ธ ๋ชจ๋ธ๋ค์ ์ ์ฅํ๋ค.
๋ค๋ฅธ ์ค์ฝํ์ session์ ์๋ก ๋ค๋ฅธ identity_map
์ ๊ฐ์ง๋ค.
์ธ์ ๋ณ๊ฒฝ๊ฐ ์ถ์
@db_test_api.route('/request_1')
class Request_1(Resource):
def get(self):
new_model = SessionTestModel(name='lee', desc='hoho')
db.session.add(new_model)
model_han = SessionTestModel.query.filter_by(name='han').first()
model_han.desc = 'jehyun-moded'
model_oh = SessionTestModel.query.filter_by(name='oh').first()
db.session.delete(model_oh)
logger.info('session.new : {}'.format(db.session.new))
logger.info('session.dirty : {}'.format(db.session.dirty))
logger.info('session.deleted : {}'.format(db.session.deleted))
db.session.flush()
logger.info('session.flush()ํธ์ถ')
logger.info('session.new : {}'.format(db.session.new))
logger.info('session.dirty : {}'.format(db.session.dirty))
logger.info('session.deleted : {}'.format(db.session.deleted))
return 200
[INFO] session.new : IdentitySet([<SessionTestModel (transient 113757904)>])
[INFO] session.dirty : IdentitySet([<SessionTestModel 16>])
[INFO] session.deleted : IdentitySet([<SessionTestModel 1>])
[INFO] session.flush()ํธ์ถ
[INFO] session.new : IdentitySet([])
[INFO] session.dirty : IdentitySet([])
[INFO] session.deleted : IdentitySet([])
ํ ์ค์ฝํ์ ์ธ์
์ ์ถ๊ฐ, ๋ณ๊ฒฝ, ์ญ์ ๋๋ ๋ชจ๋ธ ์ธ์คํด์ค๋ค์ ์ธ์
์ new
, dirty
, deleted
์์ฑ๊ฐ์ผ๋ก ์ถ์ /ํ์ธํ ์ ์๋ค.
new
: session.add()๋ก pending์ํ์ธ ๋ชจ๋ธ ์ธ์คํด์ค๋ค
dirty
: ์์ฑ๊ฐ์ด ๋ณ๊ฒฝ๋ persistent์ํ์ธ ๋ชจ๋ธ ์ธ์คํด์ค๋ค
deleted
: session.delete()๋ก detached ์์ ์ธ ๋ชจ๋ธ ์ธ์คํด์ค๋ค
flush, commit(commit์ ํ๋ฉด ๋ฐ๋์ ์ง์ ์ flush๋ฅผ ์ํ)์ ์ธ์ ์ ๋ณ๊ฒฝ๊ฐ์ด ์ ์ฉ๋๋ค.
flush๋
@db_test_api.route('/request_1')
class Request_1(Resource):
def get(self):
new_model = SessionTestModel(name='han', desc='jehyun')
db.session.add(new_model)
logger.info('session.new : {}'.format(db.session.new))
model = SessionTestModel.query.filter_by(name='han').first()
logger.info('model : {}'.format(model))
return 200
[INFO] session.new : IdentitySet([<SessionTestModel (transient 115920592)>])
[INFO] model : None
@db_test_api.route('/request_1')
class Request_1(Resource):
def get(self):
new_model = SessionTestModel(name='han', desc='jehyun')
db.session.add(new_model)
logger.info('session.new : {}'.format(db.session.new))
# ํ๋ฌ์
db.session.flush()
model = SessionTestModel.query.filter_by(name='han').first()
logger.info('model : {}'.format(model))
return 200
[INFO] session.new : IdentitySet([<SessionTestModel (transient 121364144)>])
[INFO] model : <SessionTestModel 15>
@db_test_api.route('/request_1')
class Request_1(Resource):
def get(self):
new_model = SessionTestModel(name='lee', desc='hoho')
db.session.add(new_model)
model_han = SessionTestModel.query.filter_by(name='han').first()
model_han.desc = 'jehyun-moded'
model_oh = SessionTestModel.query.filter_by(name='oh').first()
db.session.delete(model_oh)
for value in db.session.identity_map.values():
logger.info(value)
db.session.flush()
logger.info('session.flush() ํธ์ถ')
for value in db.session.identity_map.values():
logger.info(value)
return 200
[INFO] <SessionTestModel 16> <-- SessionTestModel.query.filter_by(name='han').first() ์กฐํ ํ ์์
[INFO] <SessionTestModel 1> <-- SessionTestModel.query.filter_by(name='oh').first() ์กฐํ ํ ์ญ์ ์์ฝ
[INFO] session.flush() ํธ์ถ
[INFO] <SessionTestModel 16> <-- SessionTestModel.query.filter_by(name='han').first() ์์ ๋ ๋ชจ๋ธ
[INFO] <SessionTestModel 24> <-- SessionTestModel(name='lee', desc='hoho') ์๋ก ์์ฑ๋ ๋ชจ๋ธ
SessionTestModel.query.filter_by(name='oh').first() ๋ ์ญ์ ๋จ
flush๋ฅผ ํ์๋๋ ์ธ์ ์ ORM ๋งคํ์ด ๊ฐฑ์ ๋๋ค.
flush๋ฅผ ํด๋ DB์๋ ์ ์ฉ๋์ง ์๋๋ค.