2021. 8. 18. 00:08ㆍSERVER/Flask
Object Relational Mapping
객체 관계 매핑, 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를
변환하여 같은 객체 타입으로 사용하기 위한 데이터 변환 프로그래밍 기법이라고 생각하면 된다
테이블 : question
위와 같이 구성된 question 테이블에 새로운 데이터를 삽입하기 위한 쿼리문은 아래와 같다
insert into question (subject, content) values ("안녕하세요", "가입 인사드립니다 ^^");
insert into question (subject, content) values ("질문 있습니다", "ORM이 궁금합니다");
아래는 위 쿼리문을 ORM을 사용하여 작성한 파이썬 코드이다
question = Question(subject="안녕하세요", content"가입 인사드립니다 ^^")
db.session.add(question1)
question = Question(subject="질문 있습니다", content"ORM이 궁금합니다")
db.session.add(question2)
보기에 코드가 양이 많아진 것 같지만, 쿼리문을 별도로 작성하지 않아도 된다는 장점이 있다
코드에서 Question은 파이썬 클래스(class)를 의미한다
여기서 Question이 데이터를 관리하는데 사용하는 ORM 클래스 모델이라고 한다
이 외에도 추가적인 장점을 말하면 DB 종류에 상관 없이 일관된 코드를 유지할 수 있게 된다
즉, 유지 · 보수 측면에서 매우 큰 이점을 가지게 된다
또한 내부에서 안전한 SQL 쿼리를 자동으로 생성해주기 때문에 관리하게 될 개발자가 서로 달라도
통일된 쿼리를 작성할 수 있어 오류 발생률을 현저하게 낮출 수 있다
ORM Model
class User(db.Model):
__tablename__ = 'User'
user_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
user_name = db.Column(db.String(20, 'utf8mb4_unicode_ci'))
user_email = db.Column(db.String(50, 'utf8mb4_unicode_ci'))
user_pw = db.Column(db.String(20, 'utf8mb4_unicode_ci'))
class User(db.Model);
클래스 유저가 db.Model을 상속하는 것, db.Model은 어디서 왔을까?
SQLAlchemy 패키지안에 포함되어있다
class ORM model을 사용하기 전 항상 선언해주어야하는 것이 있다
db = SQLAlchemy()
위와 같은 방식으로 db(SQLAlchemy의 모든 기능을 사용할 수 있는)객체를 생성한다
해당 db안에 포함된 Model이라는 기능을 유저 클래스에 상속시켜주게 된 것이다
__tablename__ = "테이블 이름"
ORM 모델 생성시 생략되어도 무방한 부분이다
생성할 테이블의 이름을 내가 선택적으로 짓고 싶을 때, 원하는 이름을 지어줄 수 있다
user_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
User에서 사용할 Attribute 중 하나로 id는 기본키로써 테이블의 식별자 역할을 한다
해당 id에 primary_key=True 속성을 지정해주고, null값이 들어가지 않도록 nullable=False 지정
(autoincrement=True는 id의 값이 자동으로 1씩 증가하도록 도와준다)
user_name = db.Column(db.String(20))
user_email = db.Column(db.String(50))
user_pw = db.Column(db.String(20))
각각 어떤 형태(데이터 타입)의 데이터를 저장할 것인지 명시되어있다
직접적인 데이터를 클래스 선언에서 넣어주진 않지만, 앞으로 어떤 데이터가 들어갈지 명시해준 것
(명확하게 명시해두어야 앞으로 매핑되어질 데이터들이 테이블에 잘 전달될 수 있다)
기본적으로 테이블의 값을 넣어야할 때 들어갈 값과 크기를 고려해서 설정해주어야 한다
예를 들어 이름을 입력받아야 하는데 아래와 같이 설정해주었다고 가정해보자
user_name = db.Column(db.Integer(2))
해당 설정은 숫자 타입의 데이터 2개를 입력받을 수 있다
이름을 입력받는 방법과는 거리가 굉장히 멀게 보이는 것이 느껴진다
그렇기 때문에 해당 타입과 길이를 설정하는 것은 설정 단계에서 신중하게 고려되어야 한다
유저 테이블의 Attribute 설정이 끝났다면 User의 튜플을 추가할 때 사용할 생성자를 생성한다
* 여기서 primary_key 값으로 사용되는 id는 생성 순서대로 자동으로 지정되며,
사용자가 임의 지정시 기본키로서의 기능을 상실할 수 있다
def __init__(self, user_name, user_email, user_pw):
self.user_name = user_name
self.user_email = user_email
self.user_pw = user_pw
유저 테이블의 속성에 정의되었던 이름, 이메일, 비밀번호만 초기화를 진행한다
해당 생성자를 정의해주는 이유 중 또 하나는 값을 보내줄 때 이점에 있다
user = User("Name", "Test@test.com", "Password")
위와 같은 방식으로 속성을 하나하나 지정해서 작성해주지 않아도 DB에 값을 전달할 수 있다
user = User()
user.user_name =
user.user_pw =
만약 생성자를 정의하지 않을 경우 값을 넘길 때 속성을 하나하나 지정해주어야 한다
최종 테이블의 형태 (models.py)
class User(db.Model):
__tablename__ = 'User'
user_id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
user_name = db.Column(db.String(20))
user_email = db.Column(db.String(50))
user_pw = db.Column(db.String(20))
def __init__(self, user_name, user_email, user_pw):
self.user_name = user_name
self.email = user_email
self.phone = user_pw
Flask ORM 작성
위와 같이 데이터베이스의 테이블이 작성되었다면 값을 넘겨줄 코드를 작성해야 한다
App.py
from flask import Flask
from models import User
from db_connect import db
데이터를 받아서 뿌려주게 될 App.py에서 필요한 모듈들을 불러와야 한다
데이터베이스의 테이블을 정의한 models의 유저 클래스,
SQLAlchemy의 모든 기능을 사용할 수 있는 db_connect의 db 객체를 import 해준다
이후 아래 두 줄의 코드를 정의해준다
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:root@127.0.0.1:3306/MyDB"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
SQLAlchemy를 사용하겠다는 의미로, "mysql+pymysql"이라고 적힌 부분,
사용할 데이터베이스는 MySQL이다 라고 정의준 것이다
root:root : 각각 아이디, 패스워드를 의미한다
127.0.0.1:3306 : 데이터베이스의 주소와 포트를 의미한다
MyDB : MyDB라는 이름의 데이터베이스를 의미한다
user = User("Test", "Test@Test.com", "Test1234")
db.session.add(user)
user = User()로 models에 정의된 유저 클래스에 접근할 수 있는 user 객체를 생성해준다
이후 위에서 __init__에서 설명했던 생성자 정의를 미리 해주었기 때문에
위와 같은 방식으로 괄호안에 값을 넣어줄 있게 된다
db.session.commit()
하나의 트랜잭션이 완료되면 수정된 내용을 반드시 커밋을 통해 최종 반영을 해주어야 한다
커밋을 진행하지 않을 시 아무리 변경을 시도해도 테이블의 값은 절대 바뀌지 않는다
* 더 자세한 CRUD ORM 작성법은 다음 포스트를 확인해주세요
'SERVER > Flask' 카테고리의 다른 글
8. Flask (RDB) (0) | 2021.08.12 |
---|---|
7. Flask (logging) (0) | 2021.08.06 |
6. Flask (Authentication) (0) | 2021.08.06 |
5. Flask (CRUD) (0) | 2021.08.05 |
4. Flask (Blueprint, Jinja Template) (0) | 2021.08.05 |