본문 바로가기
AI 공부/파이썬

파이썬 (SQLAIchemy)

by AI Sonny 2022. 8. 23.
728x90

SQLAIchemy

  • python에서 사용하는 대표적인 ORM

 

- ORM(Object Relational Mapping)이란?

  • 객체와 DB의 테이블이 매핑을 이루는 것을 말한다.
  • DB의 테이블 객체화시켜서 데이터를 CRUD
  • SQL을 직접 작성하지 않고, 테이블을 조작할 수 있다.
  • 사용하는 DBMS가 변경된다면 엔지만 바꿔주면 된다.
  • 쿼리 대신 메소드를 이용해서 CRUD(create....)

사용 예시

 

import sqlalchemy as db

 

구글 드라이브를 연결하고 import를 해준다.

 

  • db 접속 정보 파일
import yaml
DB_INFO = "/content/drive/MyDrive/data/db.yaml"
with open(DB_INFO,"r") as f:
    db_info = yaml.load(f,Loader=yaml.Loader)
db_info

 

나의 yaml 파일을 가져오고 read 형식으로 open해준다.

 

  • DB 연결 엔진 생성하기
conn_url = f"mysql+pymysql://{USER}:{PASSWD}@{HOST}/{DB_NAME}"
engine = db.create_engine(conn_url) # 연결 엔진이 반환된다. (반환되니 변수를 넣어줘야한다.)
engine

=> 연결된 것을 확인할 수 있다.

 

 

- 테이블과 매핑할 클래스 작성하기

  • 테이블 이름 정의
  • 컬럼 정의
  • Base 클래스를 상속 받아서 정의
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() # Base 클래스 객체의 주소가 반환된다.

 

Base에 declarative_base()를 넣어 객체의 주소가 반환 되도록한다.

 

class MovieInfo(Base):
    # 매핑할 테이블명
    __tablename__ = "tb_movie_info2"
    id = db.Column(db.Integer,primary_key = True, autoincrement = True)
    actor = db.Column(db.String(255)) # 첫번째 인수에는 타입넣기!
    director = db.Column(db.String(100))
    pubDate = db.Column(db.Integer)
    subtitle = db.Column(db.String(100))
    title = db.Column(db.String(100),nullable = False)
    userRating = db.Column(db.FLOAT)

 

클래스를 만들어준다.

 

- Base 클래스를 이용해서 테이블 생성하기

  • 테이블이 존재할 경우 생성 X
Base.metadata.create_all(engine)
  • DB의 테이블과 상호작용을 하려면 세션을 얻어야한다. (커서와 비슷)
  • sessionmaker 라는 메소드를 연결 엔진 객체에 넣어 실행하여 세션 클래스를 얻는다.
  • 세션 클래스를 실행하면 세션 객체가 반환된다.

객체 반환

Session = db.orm.sessionmaker(engine)
sess = Session()
sess

=> <sqlalchemy.orm.session.Session at 0x7f661cf27350>

 

yaml 파일을 연다.

 

import yaml
KEY_FILE = "/content/drive/MyDrive/data/local.yml"
with open(KEY_FILE,"r") as f:
    naver_keys = yaml.load(f,Loader=yaml.Loader)
naver_keys

=> 나의 키정보를 갖고온다.

 

네이버 영화 api를 가져온다.

 

from my_api import naver_api
url = "	https://openapi.naver.com/v1/search/movie.json"
params = {"query" : "검은 사제들"}
result = naver_api.search_api(url,naver_keys["CLIENT_ID"],naver_keys["CLIENT_SECRET"],params)
result

=> {'lastBuildDate': 'Tue, 23 Aug 2022 17:35:02 +0900',
 'total': 2,
 'start': 1,
 'display': 2,
 'items': [{'title': '<b>검은 사제들</b>: 지옥의 문',
   'link': 'https://movie.naver.com/movie/bi/mi/basic.nhn?code=197843',
   'image': 'https://ssl.pstatic.net/imgmovie/mdi/mit110/1978/197843_P01_101913.jpg',
   'subtitle': 'Gates of Darkness',
   'pubDate': '2019',
   'director': '돈 E. 폰트르로이|',
   'actor': '토빈 벨|랜디 셸리|',
   'userRating': '4.88'},
  {'title': '<b>검은 사제들</b>',
   'link': 'https://movie.naver.com/movie/bi/mi/basic.nhn?code=120157',
   'image': 'https://ssl.pstatic.net/imgmovie/mdi/mit110/1201/120157_P24_105439.jpg',
   'subtitle': 'The Priests',
   'pubDate': '2015',
   'director': '장재현|',
   'actor': '김윤석|강동원|',
   'userRating': '8.33'}]}

 

필요없는 컬럼을 삭제한다.

 

items = result["items"][1] # 필요없는 컬럼삭제
del items["image"],items["link"]
items

=>	 {'title': '<b>검은 사제들</b>',
 	 'subtitle': 'The Priests',
 	 'pubDate': '2015',
	 'director': '장재현|',
	 'actor': '김윤석|강동원|',
	 'userRating': '8.33'}

 

언패킹을 이용하면 내 객체에 접근해서 알아서 넣어준다!

 

movie_info = MovieInfo(**items)  # 언패킹되어 알아서 넣어준다.
movie_info.actor

=> 김윤석|강동원|

 


  • insert하기
sess.add(movie_info)
sess.commit()

 

나의 영화 리스트를 워크벤치와 연동하여 넣어보겠다.

 

영화 리스트

movie_list = [
( "명량", 2014),
( "인터스텔라", 2014),
( "해적: 바다로 간 산적",  2014),
( "수상한 그녀",2014),
( "국제시장",2014),
( "트랜스포머: 사라진 시대",2014),
( "군도: 민란의 시대",2014),
( "엣지 오브 투모로우",2014),
( "엑스맨: 데이즈 오브 퓨처 패스트",2014),
( "어메이징 스파이더맨 2",2014),
( "타짜-신의 손",2014),
( "혹성탈출: 반격의 서막",2014),
( "캡틴 아메리카: 윈터 솔져",2014),
( "역린",2014),
( "신의 한 수",2014),
]

 

결과를 보면 잘 가져온 것을 알 수 있다.

 

for title,year in movie_list:
    params = {"query" : title, "display" : 1 ,"yearfrom" : year,"yearto" : year}
    result =  naver_api.search_api(
                                url,
                                naver_keys["CLIENT_ID"],
                                naver_keys["CLIENT_SECRET"],
                                params
                                )
    items = result["items"][0] # 필요없는 컬럼삭제
    del items["image"],items["link"]
    movie_info = MovieInfo(**items)
    sess.add(movie_info)
sess.commit()
result = sess.query(MovieInfo).all() # select * from 테이블명
result

=>	[<__main__.MovieInfo at 0x7f661c835690>,
	 <__main__.MovieInfo at 0x7f661c835d50>,
	 <__main__.MovieInfo at 0x7f661c835c90>,
	 <__main__.MovieInfo at 0x7f661c835fd0>,
	 <__main__.MovieInfo at 0x7f661c835d90>,
	 <__main__.MovieInfo at 0x7f661c835310>,
	 <__main__.MovieInfo at 0x7f661c835f50>,
	 <__main__.MovieInfo at 0x7f661c8355d0>,
	 <__main__.MovieInfo at 0x7f661c835d10>,
	 <__main__.MovieInfo at 0x7f661c835e10>,
	 <__main__.MovieInfo at 0x7f661c835a50>,
	 <__main__.MovieInfo at 0x7f661c835490>,
	 <__main__.MovieInfo at 0x7f661c835790>,
	 <__main__.MovieInfo at 0x7f661c835750>,
	 <__main__.MovieInfo at 0x7f661c838bd0>,
	 <__main__.MovieInfo at 0x7f661d21ebd0>]

 

코드를 좀 더 효율적으로 짜기위해  add_all을 이용하여 보았다.

 

add_all을 이용하면 데이터베이스에 과부하를 방지할 수 있다.

 

tmp = [] 
for title,year in movie_list:
    params = {"query" : title, "display" : 1 ,"yearfrom" : year,"yearto" : year}
    result =  naver_api.search_api(
                                url,
                                naver_keys["CLIENT_ID"],
                                naver_keys["CLIENT_SECRET"],
                                params
                                )
    items = result["items"][0] # 필요없는 컬럼삭제
    del items["image"],items["link"]
    movie_info = MovieInfo(**items)
    tmp.append(movie_info)
sess.add_all(tmp)
sess.commit()

 

처음에 for문을 통해 params와 result를 이용하여 정보를 가져오고,

 

items 변수를 선언하여 필요없는 컬럼을 삭제한다.

 

append를 하여 새로운 리스트에 담아낸다. 이 후 add_adll을 이용하여 반환하면 한번에 반환할 수 있다.

 


오늘은 처음에는 막막했으나 나중에 잘 풀려서 기분이 좋아졌다..ㅎ

728x90

댓글