hello.py
from flask import Flask
import os
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__)) #파일의 절대경로 저장
db_url = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_DATABASE_URI'] = db_url
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app) #SQLAlchemy를 인스턴스화
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
loginname = db.Column(db.String(64), unique=True, index=True)
# relationship
role_id = db.Column(db.Integer, db.ForeignKey("roles.id"))
def __repr__(self):
return "<User {}>".format(self.loginname)
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
rolename = db.Column(db.String(64), unique=True)
# relationship
users = db.relationship('User', backref='role')
def __repr__(self):
return "<Role {}>".format(self.rolename)
@app.shell_context_processor
def make_shell_context():
return dict(db=db, User=User, Role=Role)
파이썬 데이터베이스 프레임워크
파이썬은 오픈소스와 상용 데이터베이스에 대한 대부분의 엔진을 위한 패키지를 갖고 있다. flask는 어떤 데이터베이스 패키지를 사용하든 제한이 없으므로 원한다면 MySQL, Postgre, SQLite, 레디스, 몽고DB, 카우치DB를 사용할 수 있다.
평가 요소
-사용 편의성
-성능
-호환성
-플라스크 통합
Flask-SQLAlchemy를 이용한 데이터베이스 관리
Flask-SQLAlchemy는 플라스크 어플리케이션 안에 있는 SQLAlchemy의 사용을 간단하게 하는 플라스크 확장이다. SQLAlchemy는 여러 데이터베이스 백엔드를 지원하는 강력한 관계형 데이터베이스 프레임워크다.
Flask-SQLAlchemy는 관리자 모드에서 pip를 사용하여 설치한다.
설치 코드
pip install flask-sqlalchemy
Successfully installed flask-sqlalchemy 라는 메세지가 보인다면 성공이다.
Flask-Alchemy에서, 데이터베이스는 URL로서 지정된다.
위 url에서 hostname은 데이터베이스 서비스를 제공하는 서버를 말한다.
이 글에서 SQLite 데이터베이스를 사용하려고 한다.
SQLite는 서버를 가지고 있지 않으므로 hostname, username, password는 데이터베이스에 대한 파일이름이 된다.
환경설정
#1.테이블 만들기
db.create_all() 함수는 db.Model에 대응하는 모든 subclass들을 찾고 이에 대응하는 테이블들을 DB에 저장한다.
>>> from hello import db
>>> db.create_all()
위 코드를 실행한 후 디렉터리를 체크하면 data.sqlite라는 새로운 파일이 생긴 것을 확인할 수 있다.
#2.행 추가하기
>>> admin_role=Role(rolename='Admin')
>>> mod_role=Role(rolename='Modertor')
>>> user_role=Role(rolename='User')
>>> user_john=User(loginname='john', role=admin_role)
>>> user_susan=User(loginname='susan', role=user_role)
>>> user_david=User(loginname='david', role=user_role)
오브젝트는 단지 Python에만 존재하며 아직 DB에는 작성되지 않았다. id값이 설정되지 않았기 때문이다.
>>> print(admin_role.id)
None
>>> print(mod_role.id)
None
>>> print(user_role.id)
None
DB에 대한 변화는 session을 통해 관리된다. Flask-SQLAlchemy에서는 db.session으로 제공한다.
데이터베이스 작성을 위해 오브젝트를 준비하기 위해서는 오브젝트가 session에 추가되어야 한다.
DB에 오브젝트를 작성하기 위해서 commit()을 해야한다는 점 잊지말자.
>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)
>>> db.session.commit()
행의 수정
admin_role.rolename = 'Administrator'
db.session.add(admin_role)
db.session.commit()
행의 삭제
db.session.delete(mod_role)
db.session.commit()
다시 id속성을 체크해보면
>>> print(admin_role.id)
1
>>> print(mod_role.id)
2
>>> print(user_role.id)
3
#3. 행의 쿼리 사용하기
Flask-SQLAlchemy는 각 Model 클래스마다 query 객체를 사용할 수 있다.
모델을 위한 가장 기본적 쿼리는 그에 대응하는 테이블의 전체 내용을 리턴하는 것이다.
filters의 사용을 통해 더 정확한 database검색을 실행할 수도 있다.
>>> Role.query.all()
[<Role Admin>, <Role Modertor>, <Role User>]
>>> User.query.all()
[<User john>, <User susan>, <User david>]
>>> User.query.filter_by(role=user_role).all()
[<User susan>, <User david>]
native SQL쿼리문을 조사할 수도 있다.
>>> str(User.query.filter_by(role=user_role))
'SELECT users.id AS users_id, users.loginname AS users_loginname, users.role_id AS users_role_id \nFROM users \nWHERE ? = users.role_id'
쉘 세션을 종료(exit()) 하면 이전 예제에서 생성된 객체들은 파이썬 객체로서 존재를 멈추고 데이터베이스 테이블에 있는 행으로 존재하게 된다. 새로운 쉘 세션을 시작한다면 데이터베이스 행에서 파이썬 객체를 재생성해야한다.
종료 후 확인했을 때 오류가 나타나는 것을 확인할 수 있다.
>>> exit()
(flask) D:\subject\class-mobile-programming\ch06>flask shell
Python 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)] on win32
App: hello [production]
Instance: D:\subject\class-mobile-programming\ch06\instance
>>> print(admin_role.id)
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'admin_role' is not defined
>>> print(mod_role.id)
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'mod_role' is not defined
>>> print(user_role.id)
Traceback (most recent call last):
File "<console>", line 1, in <module>
NameError: name 'user_role' is not defined
>>> db
<SQLAlchemy engine=sqlite:///D:\subject\class-mobile-programming\ch06\data.sqlite>
>>> User
<class 'hello.User'>
데이터베이스 행에서 파이썬 객체를 재생성하는 방법
'User' 라는 이름의 사용자 규칙을 로드하는 쿼리를 호출한다.
>>> user_role=Role.query.filter_by(rolename='User').first()
>>> user_role
<Role User>
위의 경우 query가 all() 대신에 first() 메서드로 실행되었다.
all()은 질의 모든 결과들을 list로 리턴한다.
first()는 첫번째 결과 혹은 결과가 없으면 None을 리턴한다.
'Web developer > Flask' 카테고리의 다른 글
[Flask] Jinja2 Template #1 (0) | 2020.10.30 |
---|---|
[Flask] Bootstrap (0) | 2020.10.30 |
[Flask] Blueprint (0) | 2020.10.24 |
[Flask] 대규모 Application 구조 (0) | 2020.10.24 |
[Flask] SQLAlchemy #2 (0) | 2020.10.14 |
댓글