728x90

python 에서 orm을 사용할일이 생겨서 orm을 찾던중 sqlAlchemy 는 너무 문서가 잘 읽히지 않고 옜날 느낌이라서..

https://docs.sqlalchemy.org/en/14/

 

SQLAlchemy Documentation — SQLAlchemy 1.4 Documentation

 

docs.sqlalchemy.org

 

좀더 문서화가 잘 되어있고 github 에서도 star 가 많은것을 찾다가 peewee를 찾게되었습니다.

http://docs.peewee-orm.com/en/latest/

 

peewee — peewee 3.14.4 documentation

Peewee is a simple and small ORM. It has few (but expressive) concepts, making it easy to learn and intuitive to use. Note If you find any bugs, odd behavior, or have an idea for a new feature please don’t hesitate to open an issue on GitHub or contact m

docs.peewee-orm.com

 

문서화도 잘되어 있고 Mysql, postgres, sqlite3 ..등 많은 sql driver 를 지원해줘서 사용하게 되었습니다.

 

Connection

domain/base.py

from peewee import PostgresqlDatabase, Model
from playhouse.reflection import generate_models
import logging

from config import conf

logger = logging.getLogger("peewee")
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)

db_url = conf.DATABASE["URL"]
user_id = conf.DATABASE["USER_ID"]
user_password = conf.DATABASE["USER_PASSWORD"]

psql_db = PostgresqlDatabase(
    "postgres", user=user_id, password=user_password, host=db_url, port=5432
)
psql_db.connect()


class BaseModel(Model):
    """A base model that will use our Postgresql database"""

    class Meta:
        database = psql_db

 

logger 를 추가하여 SQL 쿼리문을 디버깅 할수 있게 추가하였습니다.

psql host, user id, password 를 config 파일에서 불러와 Postgresql DB를 생성하고 connection합니다.

connection 이 성공하면 True를 반환합니다.

 

BaseModel 앞으로 만들 각종 Table이 상속하게 될 부모 Class입니다. 

 

Table Class

domain/shop_device.py

from domain.base import BaseModel
from peewee import IntegerField, CharField, DateTimeField


class ShopDevice(BaseModel):
    class Meta:
        db_table = "shop_device"

    # primary_key == auto increment
    id = IntegerField(primary_key=True, db_column="shop_device_id")
    shop_id = IntegerField()
    panel_id = CharField()
    panel_maker = CharField()
    panel_size = IntegerField()
    screen_ratio = CharField()
    settop_id = CharField()
    shop_display_id = IntegerField()
    status = IntegerField()
    last_check_at = DateTimeField()
    sort_no = IntegerField()
    whole_display_path = CharField()
    thumbnail_path = CharField()
    created_at = DateTimeField()
    updated_at = DateTimeField()

 

class명이 카멜 케이스 인데 table 명은 스네이크 일때 class Meta 에 db_table에 직접 테이블명을 명시 할수 있습니다.

 

peewee는 기본적으로 id 값이 primary_key = True 라면 auto increment 도 True 입니다.

 

Create

>>> user = User(username='Charlie')
>>> user.save()  # save() returns the number of rows modified.
1
>>> user.id
1
>>> huey = User()
>>> huey.username = 'Huey'
>>> huey.save()
1
>>> huey.id
2

>>> tweet = Tweet.create(user=huey, message='Hello!')

>>> tweet = Tweet.create(user=2, message='Hello again!')

>>> User.insert(username='Mickey').execute()
3

원하는 방식중에 선택하셔서 사용하시면 될거같습니다.

 

Update

>>> for stat in Stat.select().where(Stat.url == request.url):
...     stat.counter += 1
...     stat.save()

이것은 peewee에서 지양하는 방식입니다. 여러 프로세스가 동시에 카운터를 업데이트하는 경우 경쟁 조건에 취약하기 때문입니다.

 

>>> query = Stat.update(counter=Stat.counter + 1).where(Stat.url == request.url)
>>> query.execute()

전자 대신 후자의 방식으로 업데이트 하는것을 권장드립니다.

 

Get

>>> User.get(User.id == 1)
<__main__.User object at 0x25294d0>

>>> User.get_by_id(1)  # Same as above.
<__main__.User object at 0x252df10>

>>> User[1]  # Also same as above.
<__main__.User object at 0x252dd10>

>>> User.get(User.id == 1).username
u'Charlie'

>>> User.get(User.username == 'Charlie')
<__main__.User object at 0x2529410>

>>> User.get(User.username == 'nobody')
UserDoesNotExist: instance matching query does not exist:
SQL: SELECT t1."id", t1."username" FROM "user" AS t1 WHERE t1."username" = ?
PARAMS: ['nobody']

 

Select

>>> for user in User.select():
...     print(user.username)
...
Charlie
Huey
Peewee

 

 

다른 문법들이 더 궁금하신분들은 위에 있는 공식문서 링크를 통해 확인하시면 될것 같습니다!

728x90

'Python' 카테고리의 다른 글

튜플 정렬하기 - operator itemgetter 메서드  (0) 2020.10.10
문자열 정렬하기 - ljust, center, rjust  (0) 2020.09.30
python 진법 변환  (0) 2020.09.30
몫과 나머지 - divmod  (0) 2020.09.30