[Fast api] SqlAlchemy를 이용한 DB 연결

강버섯·2021년 12월 30일
1

FAST API⚡️

목록 보기
2/5

👉 SqlAlchemy

SqlAlchemy Docs

  • Python에서 사용할 수 있는 ORM

👉 ORM(Object Relational Mapping)

객체와 관계형 데이터베이스의 자동으로 매핑(연결)해주는 프레임워크이다.
(Entity와 table들의 관계를 연결해주는 툴)

생성하는 class가 관계형 데이터베이스의 테이블을 가리키게 된다.
ex. class Pet = 데이터베이스 pet table

👉 연결 생성하기

1. connection 생성(mapping 선언)

from sqlalchemy.orm import declarative_base

Base = declarative_base()

2. 연결

  • session 생성 -> engine 연결
from sqlalchemy import create_engine

# echo를 true로 설정하면 command창에 실행된 sql문이 뜨게 됨
engine = create_engine([사용할 sql의 engine(dsn)], echo = True)
# dsn? 데이터 원본 이름 : 데이터베이스에 대한 연결을 설정하도록 함
# echo를 True로 설정하면 sql log가 찍히게 됨
  • PostgreSQL 사용 시 engine👇
dsn = f"postgresql+psycopg2://{db_user}:{db_password}@{db_host}:{db_port}/{db_database}"

postgreSQL을 사용하기 위해서 psycopg2-binary(sql engine) 설치가 필요하다.

  • sqlite 사용 시 engine👇
dsn = "sqlite://db.sqlite"

3. 생성할 모델 만들기

  • 생성한 Base를 기반으로 모델을 만들어낸다.
  • _ tablename _ 을 필수적으로 선언해야한다.
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
from sqlalchemy.orm import relationship

from board.domain.board import PostInfo
from board.repositories.base import Base

from datetime import datetime

from board.utils import ToEntity


class DBUser(Base):
    __tablename__ = 'users' # 필수적으로 선언 -> table의 이름

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    email = Column(String, nullable=False)
    password = Column(String, nullable=False)
    inactivate = Column(Boolean, default=False)
  • relationship 생성
    relationship이 작성된 쪽이 다른 쪽을 참조한다.
from sqlalchemy.orm import relationship

#relation을 사용할 model 내부에
relationship(연결할 model, [options,,,,,])
#options 
#ex. back_populate : relation에서 연결된 부분에서 접근할시의 이름
#order by : model명.id -> id순으로 정렬

4. schema 생성

  • 데이터베이스를 초기 생성할 때에는 create_all을 사용해서 생성하도록 한다.
  • 최초 한 번만 create_all을 사용한다.
Base.metadata.create_all(engine) #1.에서 만든 base와 2.에서 만든 engine을 사용
  • 만일 이미 존재하는 database에 연결할 때에는 create_all이 아닌 bind를 사용
Base.metadata.bind = engine

5. session 생성

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)

#혹은

Session = sessionmaker()
Session.configure(bind=engine)
  • context class를 사용하면 session의 관리를 더 수월하게 할 수 있다.
    • __enter__ : with문이 시작될 때 실행되고 return하는 값이 변수에 들어간다.
    • __exit__ : with문 종료 시 실행된다.
class SessionContext:
	session = None
    
    def __enter__(self):
    	self.session = Session()
        return self.session
        
        
   def __exit__(self):
   	self.session.close()
    
    
with SessionContext() as session:
	# DB 작업 작성

👉 사용하기

with문으로 session을 생성한 후에 실행하도록 한다.

✏️ CRUD

  • CREATE: table에 정보 넣기
def create():
	ed_user = User(name='ed', fullname='Ed Jones', nickname='edsnickname')
	session.add(ed_user) #값 add하고
	#commit을 하면 data가 table에 삽입됨
	session.commit()

def create_all():
	session.add_all([User(....), User(....), ......]) #한 번에 여러값을 삽입
  • READ: table에 있는 정보 불러오기
def get():
	user1.session.query(User).first() #User table의 첫번째 값을 불러옴

	#filter를 사용해 원하는 값을 불러올 수 있음
	session.query(User).filter(User.name.in_(['Edwardo', 'fakeuser'])).all()

def get_all():
	session.query(User, User.name).all() #User 객체와 User 중 이름만을 select함
  • UPDATE: table에 있는 정보 갱신하기
def update(item_id):
	# 해당하는 아이템 찾아오기
	item = session.query(User).filter(User.id==item_id).first()
    	# 값 변경 진행
        
        # DB에 갱신 값 저장
        session.add(item)
        session.commit()
  • DELETE: table에 있는 정보 삭제하기
def delete(item_id):
	session.query(User).filter(User.id==item_id).delete()
    	session.commit

✏️ filter_by vs. filter

두 함수 모두 원하는 정보를 filtering 하기 위해 사용한다.

  • filter_by : 결과물 filtering
  • filter : filter_by보다 좀 더 유연한 SQL 표현을 사용할 수 있다.
    -> filter 연산자를 사용할 수 있다.
    • equals : ==
    • not equals : !=
    • like : User.name.like('%ed%')
    • match : User.name.match('wendy')

✏️ pagination

offsetlimit를 이용해서 paging을 할 수 있다.

with MakeSession() as session:
	query = session.query(DBPost)
    
    # pagination 진행 안하는 경우
    if not page:
    	posts = query.all()
    
    # pagination 진행
    else: 
    	offset = (page - 1) * page당 개체의 수
        posts = query.offset(offset).limit(page당 개체의 수).all()
  • offset : 몇번째 페이지인지 지정한다.(0부터 시작)
  • limit : 몇 개의 값을 불러올 것인지 지정한다.
profile
무럭무럭 버섯농장

0개의 댓글