python/SQLAlchemy

SQLAlchemy에서 ORM 활용하기

seokhyun2 2022. 9. 4. 21:43
이전 글(https://seokhyun2.tistory.com/84)에서 SQLAlchemy에 대해서 소개를 해보았는데요.
오늘은 ORM을 활용하는 방법을 준비해보았습니다.
 
ORM을 사용하기 위해서는, table에 매핑되는 class를 선언해서 사용하면 되는데요.
바로 예제 코드를 보도록 하겠습니다.
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.sql import func

Base = declarative_base()


class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    nickname = Column(String)
    created_at = Column(DateTime, nullable=False, server_default=func.now())

    def __repr__(self):
        return "<User(name='%s', nickname='%s')>" % (self.name, self.nickname)

ORM으로 활용하는 class는 위와 같이 선언해주시면 됩니다.

Base는 꼭 상속받아야 하고, table name을 지정해주고 Column들을 작성하면 됩니다.

맨 아래의 __repr__ 함수는 python에 존재하는 representation 메소드로 선언을 하지 않아도 상관없습니다.

선언해서 사용하는 경우, 아래와 같이 조금 더 예쁘게 원하는 데이터만 볼 수 있습니다.

>>> user = User(name="name", nickname="nickname")
>>> user
<User(name='name', nickname='nickname')>

 

위의 선언된 class를 활용하여 데이터베이스에 table을 생성해 줄 수도 있습니다.

아래와 같이 create_all 이라는 함수를 활용하면 Base를 상속받아 선언된 모든 class에 대해서, table이 생성됩니다.

Base.metadata.create_all(engine)
 
ORM을 활용하는 목적이 코드로 테이블을 바로 관리하면서, query 실수를 줄이고 코드의 재사용성도 높이는 등의 목적이 큽니다.
그런 맥락에서 서비스에서 ORM을 활용하는 경우에는, 처음에 선언된 class와 데이터베이스의 table이 매핑이 잘 되는지 확인하면 좋습니다.
만약 코드에선 class에 Column을 추가했는데 DB에는 추가가 안되어 있거나, 그 반대의 경우에 서비스 장애로 이어질 수 있기 때문입니다.
아래와 같이 inspect 함수를 활용하면 DB의 table과 Column 정보들을 받아올 수 있으며, Base로 코드에서 선언된 table들과 비교를 해보면 됩니다.
from sqlalchemy import inspect

inspector = inspect(engine)
itables = inspector.get_table_names()
for table in Base.metadata.tables.keys():
    if table not in itables:
        raise Exception(f"{table} table not exist")
    else:
        icolumns = set([(c['name'], str(c['type'])) for c in inspector.get_columns(table)])
        columns = set([(c.name, str(c.type)) for c in Base.metadata.tables[table].columns])
        if icolumns != columns:
            raise Exception(f"{table} columns mapping error")
 

이제 선언된 class들을 활용하여 DB에 읽고 쓰고 등의 작업을 해보도록 하겠습니다.

ORM으로 활용하기 위해서는 선언한 engine을 session으로 래핑해주어야 합니다.

session을 선언하는 방법은 아래와 같습니다.

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()

 

드디어 ORM을 활용할 준비가 모두 끝이 났습니다.

조금 복잡하지만 여기까지 준비를 하고 나면, ORM으로 쉽고 간편하게 DB 작업을 할 수 있습니다.

 

먼저 insert는 아래와 같이 class를 활용하여 객체를 생성해서 add 함수만 호출하면 됩니다.

user = User(name="name", nickname="nickname")
session.add(user)

 

select는 아래와 같이 사용하시면 됩니다. filter 함수가 where에 해당됩니다.

user = session.query(User).filter(name="name").first()

 

ORM을 사용하는 방법에 대해서 한번 알아보았는데요.

초기 설정은 조금 복잡하고, ORM을 처음 접하는 경우에는 물론 러닝커브도 존재합니다.

하지만, 이렇게 세팅해서 사용하게 되면, query를 직접 날리는거에 비해서 코드도 더 관리가 잘 되고 DB를 굳이 안 보고도 table이 이미 코드에 다 작성되어 있어서 코딩도 더 쉬워집니다.

 

django 같은 경우에는 django orm이 따로 존재하지만, flask나 fastapi 같은 가벼운 프레임워크를 사용하는 경우에는 sqlalchemy를 활용해보시는 것을 추천드립니다.

'python > SQLAlchemy' 카테고리의 다른 글

SQLAlchemy ORM & async 활용 (2.0.X)  (0) 2023.02.26
SQLAlchemy 소개 및 활용법  (0) 2022.08.21