Model.query VS db.session.query() 뭐가 다르지?
오늘 팀원분이 아래와 같은 질문를 주셨다.
sqlAlchemy에서 <model>.first() 쿼리로 조회된 데이터를
dict나 형태로 형변환을 해서 확인을 해보고 싶은데 왜 _asdict()가 안될까요🤔;;;
Flask에서 sqlalchemy를 사용하다보면 object.query와 session.query()를 편의에 따라 혼용해서 사용한다.
반환된 데이터를 조작하는 방법이 비슷해서 두 객체가 같을거라고 보통 생각하지만,
반환된 커리의 type을 로그로 찍어보면 사실 전혀 다른 객체임을 알 수 있다.
$ Model.query: <class 'app.model.Model'>
$ db.session.query: <class 'sqlalchemy.util._collections.result'>
Model.query와 db.session.query()의 차이점을 좀더 자세히 알아보자.
Model.query
이 방법은 주로 Flask SQLAlchemy에서 사용된다.
Flask SQLAlchemy는 Flask와 SQLAlchemy를 통합하는 라이브러리이다.
예를 들어 아래처럼 Flask SQLAlchemy의 Model을 통해 User라는 모델을 정의해보자.
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'users' # 테이블 이름
id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True)
email = Column(String(100))
def __init__(self, username, email):
self.username = username
self.email = email
Model은 Flask SQLAlchemy 모델 클래스를 나타내며, __tablename__ = 'users'로 설정하면 모델은 "users" 테이블과 연결 되고, SQLAlchemy는 해당 모델에 대한 쿼리 객체를 자동으로 생성한다.
이 쿼리 객체는 모델 클래스와 연결되고, 해당 테이블에 대한 쿼리를 수행할 때 아래와 같이 사용 할 수 있다.
# User 모델을 대상으로 쿼리를 생성
user = User.query.filter_by(username='john').first()
db.session.query()
db.session.query() 메서드는 SQLAlchemy에서 일반적으로 쿼리를 생성하는 방법이다.
이 방법은 특정 모델과 관련이 없고, 쿼리 생성의 자유도가 높다.
db.session.query()를 사용하면 특정 모델 클래스가 아닌 데이터베이스 객체에 대한 쿼리를 생성할 수 있다.
명시적으로 세션을 생성한 다음 db.session.query(User)를 사용하여 User 테이블에 대한 쿼리를 생성한다.
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
# User 모델이 아닌 특정 테이블에 대한 쿼리를 생성
user = db.session.query(User).filter_by(username='john').first()
어떤 방법이 더 선호될까?
작업 중인 모델이 하나뿐이라면 Model.query의 쿼리가 더 간결하여 사용하기 좋다.
하지만 여러 모델을 쿼리하거나 고급 쿼리 옵션을 필요로 하는 경우에는 db.session.query()를 사용해야 한다.
따라서 두가지 쿼리 방법 중 요구사항과 상황에 따라 알맞은 방법을 선택해서 사용하면 된다.
쿼리 결과 형변환
초반에 언급했듯이, 두개의 쿼리가 반환하는 데이터가 다르기 때문에 형 변환도 다르게 진행해야 한다.
Users.query.first()의 결과는 __dict__를 사용한다.
db.session.query(Users).first()의 결과는 _asdict()를 사용한다.
__dict__
__dict__ 는 파이썬에 내장된 매서드이다.
객체의 모든 속성을 가져와 dict로 변환하므로 데이터베이스 모델 객체에 정의되지 않은 속성 및 메서드도 가져오게된다.
result = Users.query.filter_by(some_field='some_value').first()
# result 객체의 __dict__ 속성 사용
result_dict = result.__dict__
_asdict()
_asdict() 메서드는 SQLAlchemy에서 제공하는 메서드로,
SQLAlchemy 모델 객체를 collections.OrderedDict 형식의 dict로 변환한다.
$ db.session.query: <class 'sqlalchemy.util._collections.result'>
user = db.session.query(Users).first()
user_dict = user._asdict()
마무리
Model.query에서 _asdict()를 사용 할 수 없는 이유
_asdict() 메서드는 SQLAlchemy 객체의 메서드로, SQLAlchemy 인스턴스 또는 모델 객체에 대해 사용할 수 있다.
Model.query로 쿼리한 결과는 SQLAlchemy 모델 객체가 아닌 ORM 객체이므로 _asdict() 메서드를 사용할 수 없다.
'# Development > Database' 카테고리의 다른 글
[ORACLE] 오라클 분석(Oracle Analyze), 통계정보, 실행계획 (Execution Plan) : Part1-용어이해 (0) | 2024.07.21 |
---|---|
[SQLAlchemy] 트랜잭션(transaction) 관리: add, flush, commit 메서드의 활용 (0) | 2023.10.26 |
[SQL - Error] utf8mb4_0900_ai_ci, utf8mb4_general_ci (0) | 2023.01.12 |
[SQL] 쿼리문 실행 순서 (0) | 2022.06.27 |