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
'AI 공부 > 파이썬' 카테고리의 다른 글
파이썬 (Pandas 기초) (0) | 2022.08.30 |
---|---|
파이썬 (Numpy) (0) | 2022.08.24 |
파이썬 (Pymysql) (0) | 2022.08.23 |
파이썬 (pip와 가상 환경) 마지막! (0) | 2022.08.10 |
파이썬 (파일(JSON) 입출력, 구글 드라이브 마운트, YAML, pickle 모듈) (0) | 2022.08.10 |
댓글