본문 바로가기

Web/Web

sqlalchemy로 Django DB를 mysql로 세팅하기 1 ( DB접속 및 모델생성 하기)

 

 

모든 코드의 바탕은 sqlalchemy의 Docs기반입니다

(https://docs.sqlalchemy.org/en/13/orm/tutorial.html)

 

Insight

 

- print(‘python manage.py migrate 안녕…')

- SELECT "Hello World!";

- 파이썬 쉘 스크립팅을 통한 DB table 생성 및 접속

- 무엇인지 알았지만 어디서 쓰이는지 백엔드 서버입장에서 다시 보이게 되는 Oracle DB의 instance

아름답고 또 토나온다

 

 

Django에서 기존 DjanoORM을 안쓰고 SQLalchemy(ORM)로 쓰는 이유는? 

 

 1.실제 DB의 운영과 맞지 않습니다. (기본적인  CRUD 사용할 것은 괜찮음)

 2.기존장고ORM은 N+1 쿼리문제시 for문으로 쿼리를 요청하면  쿼리가 매우 많아져 대용량 데이터 처리에 매우 비효율적 입니다.

(https://zetawiki.com/wiki/N%2B1_%EC%BF%BC%EB%A6%AC_%EB%AC%B8%EC%A0%9C) [쿼리는 비싸다....]

 

2-1. 기존ORM에서 select_related()라는 함수로 쿼리를 한 번만 불러와서 해결 시켜줄 수있지만

       foreign_key, one-to-one 관계에서만 해결이 되는 것이고 (Inner Join문 을사용하는 한번의 

       쿼리)

       many-to-one, many-to-many 는 prefetch_related()를 사용하는데 메인쿼리 이외 별도 

      쿼리들을 생성하여 실행시킨다.

2-2. 위와 같이 제한적으로 핸들링은 할수 있지만 sql.raw()나 다른 직접 sql을 쓰는 ORM을 

      직접 DB를 컨트롤 하기에는 효과적입니다.!

 

3.DjangoORM은 대용량 사용하기에 아직까진 부족한 면이 있습니다.(하지만 꾸준한 업데이트로 Djanog3.0버전 릴리즈 장고 짱!)

 

더 자세한 비교는 여기 (https://www.eversql.com/django-vs-sqlalchemy-which-python-orm-is-better/)

 

기존의 셋팅 환경 

 

- 환경은 ubuntu 18.04에서 진행하였습니다.

- 가상환경은 conda를 활용하였습니다.

- 파이썬은 3.7버전이고 

- mysql-server는 5.7버전을 사용 하였습니다.

  (mysql-server 8.0버전과 그 이상은 거의 비슷하나

  https://mysql.wisborg.dk/2019/03/03/using-sqlalchemy-with-mysql-8/ 

  를 참조 하세요)

 

필요한 사전 지식

 

SQL(DDL,DML,DCL)

Cases by DB setting in Django models 

Python OOP (__init__,__repr__ Magic method), Sequence

MysqlDB, Pool, Cache, Transaction, Session,Dialect.DBAPI(https://docs.sqlalchemy.org/en/13/core/engines.html)

 

필요한 라이브러리

 

Conda 내

 

- sqlalchemy(SQL-ORM)

 

- mysqlclient(DBAPI)

 

- Shapely(mysqlclient가 잘 설치 안될때)



사전 설치 



1.conda에서 mysqlclient를 설치하기 전 터미널에서 세팅을 해줘야 합니다.

 

파이썬 라이브러리로서  sqlalchemy 공식 Docs에서는 mysqlclient PyMySQL을 권장합니다. 



https://pypi.org/project/mysqlclient/

(macOS 및 py2버전 은 위의 링크에 있습니다.)

 

리눅스에 원하는 환경에 맞추어 python3-dev를 

sudo apt-get install python3-dev # debian / Ubuntu

sudo yum install python3-devel # Red Hat / CentOS

- 그래도 안된다면

  • sudo apt-get install python-dev default-libmysqlclient-dev # Debian / Ubuntu
  • sudo yum install python-devel mysql-devel # Red Hat / CentOS
  • brew install mysql-client # macOS (Homebrew)

기본 요건을 설치 후 conda에서  mysqlclient를 설치

 

pip install mysqlclient 

 

#사전 설치 issue가 좀 있어서 에러가 나시면 아래의 링크의 댓글을 참조 

부탁드립니다(https://elfinlas.github.io/2019/01/23/pip-mysql-error/)




2.conda에서 sqlalchemy 설치합니다.

 

pip install sqlalchemy

 

3.settings.py 에서의  DATABASES관련 주석처리 합니다.

 

따로 모듈 파일을 만들어서 사용하겠습니다.

 

추가로 경고 메시지 무시를 위해 아래와 같은 코드를 맨 밑에 넣어 줍니다. 

 

##Stop Warning about '/'
 
APPEND_SLASH=False

 

 

전체 코드 보기

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
 
#데이터 베이스에 접속한다.
DATABASES = create_engine('mysql+mysqldb://<user>:<password>@<localhost>:<port>:<databaseName>', echo = True)
 
# orm과의 매핑을 명시하는 함수를 선언한다.
Base = declarative_base()
 
class Tada(Base):
 
   __tablename__ = 'tada'
 
   id       = Column(Integer, primary_key=True)
   name     = Column(String(50))
   fullname = Column(String(50))
   password = Column(String(50))
 
   def __init__(self, name, fullname, password):
 
       self.name     = name
       self.fullname = fullname
       self.password = password
 
   def __repr__(self):
       return "<Tada('%s', '%s', '%s')>" % (self.name, self.fullname, self.password)
 
if __name__ == '__main__':
 
   #  Database를 없으면 생성 또는 사용의 의미 django에서  create_or_update() (table) 같은것
   Base.metadata.create_all(DATABASES)
  
   # 세션을 만들어서 연결시킨다.
   Session = sessionmaker()
   Session.configure(bind=DATABASES)
   session = Session()
 
   # 위의 클래스,인스턴스 변수를 지킨 다음에
   tada = Tada('ks','ks','1111')
 
   # 세션에 추가를 한다.
   session.add(tada)
   session.commit()
 

 

 

세부 코드 보기

 

1. 데이터 베이스에 일단 접속을 합니다. <>에 필요하신 값을 대체 넣어주시면 됩니다.

(<>괄호는 넣지 않습니다)

<databaseName>는 미리 mysql에 존재하는 이름이여야 합니다.

 

#데이터 베이스에 접속한다.
DATABASES = create_engine('mysql+mysqldb://<user>:<password>@<localhost>:<port>:<databaseName>', echo = True)

 

2. ORM  mapping 을 선언 해 Base를 선언합니다. 

 

# orm과의 매핑을 명시하는 함수를 선언한다.
Base = declarative_base()

 

3. 클래스명을 선언합니다.

테이블 명은 __tablename__으로 지정합니다 (보통은 복수형으로 합니다)

 

클래스 변수에 Column을 명시하며 제약 조건도 넣습니다.

PK가 Integer일 경우 자동으로 DjangoORM의 AutoField 처럼 생성시 숫자를 증가시켜 줍니다.

 

__init__  메서드로 실제의 값이 들어가서 저장될 변수를 선언합니다.

 

__repr__ 메서드로 컬럼의 값에 맞게 설정하여 <>로  return해줍니다.

<>로 묶는것은 쿼리셋으로 처리하기 위함이고

__str__은 비공식적인, 읽기 편한 매직매서드이므로 __repr__을 사용하셔야 합니다.

 

 

class Tada(Base):
 
   __tablename__ = 'tada'
 
   id       = Column(Integer, primary_key=True)
   name     = Column(String(50))
   fullname = Column(String(50))
   password = Column(String(50))
 
   def __init__(self, name, fullname, password):
 
       self.name     = name
       self.fullname = fullname
       self.password = password
 
   def __repr__(self):
       return "<Tada('%s', '%s', '%s')>" % (self.name, self.fullname, self.password)

 

 

4. 실제로 실행할 코드를 마지막에 명세합니다.

create_all()데이터 베이스의 테이블이 있는지 없는지 없으면 생성하고 있으면 추가하는 함수입니다.

세션은 사용자의 요청이라고 이해하시면 편합니다.

사용자 요청을 만들어 세션을 준비하고

원하는 row를 실어서 

session.add()

session.commit()

합니다

 

if __name__ == '__main__':
 
   #  Database를 사용의 의미 django에서  create_or_update() (table) 같은것
   Base.metadata.create_all(DATABASES)
  
   # 세션을 만들어서 연결시킨다.
   Session = sessionmaker()
   Session.configure(bind=DATABASES)
   session = Session()
 
   # 위의 클래스,인스턴스 변수를 지킨 다음에
   tada = Tada('ks','ks','1111')
 
   # 세션에 추가를 한다.
   session.add(tada)
   session.commit()

 

 

*

mysql 5.7에서의 rank, rownum 함수는 따로 지원이 안되므로 아래의 링크를 참조 하길 바랍니다.

 

https://stackoverflow.com/questions/54239851/mysql-5-7-getting-the-row-number

mysql 5.7 rank, rownum

 

**

쿼리셋과 캐싱

쿼리셋은 DB에 Access 할 때 캐시 메모리를 포함하고 있습니다. 처음 쿼리셋이 연산될 때, 캐시가 비었기 때문에 Query가 발생합니다.  그 이후 동일한 쿼리셋을 사용할 경우 추가적인 Query는 발생하지 않고, 캐시에서 꺼내서 사용합니다.

(https://jay-ji.tistory.com/35)



***sqlalchemy cheatsheet

https://towardsdatascience.com/sqlalchemy-python-tutorial-79a577141a91

https://www.pythonsheets.com/notes/python-sqlalchemy.html

 

****reference

https://docs.sqlalchemy.org/en/13/orm/tutorial.html

'Web > Web' 카테고리의 다른 글

장고에서 Unittest하기  (0) 2019.11.12