본문 바로가기
플라스크

Define and Access the Database(데이터베이스 정의와 접근)

by dharana7723 2021. 8. 18.

https://flask.palletsprojects.com/en/2.0.x/tutorial/database/

 

Define and Access the Database — Flask Documentation (2.0.x)

Define and Access the Database The application will use a SQLite database to store users and posts. Python comes with built-in support for SQLite in the sqlite3 module. SQLite is convenient because it doesn’t require setting up a separate database server

flask.palletsprojects.com

데이터베이스 정의 및 접근

 

어플리케이션은 SQLite 데이터베이스를 유저와 포스트를 저장하기 위해 사용할 것입니다. 파이썬은 sqlite3 모듈에서 SQLite를 위한 빌트인을 지원합니다.

 

SQLite는 각 데이터베이스 서버를 설정할 필요할 필요가 없으며 파이썬에 빌트인 되어있기 때문에 편합니다. 그러나, 만약 동시 요청이 데이터베이스를 동시에 쓰려 시도한다면, 그것은 느려지며 각 write가 순차적으로 이루어지도록 할 것입니다. 작은 어플리케이션들은 이것을 인지하지 않지만 어플리케이션이 커진다면, 당신은 다른 데이터베이스로 전환하길 원할 것입니다.

 

튜토리얼은 SQL에 대해 자세히 들어가지 않습니다. 만약 당신이 이것에 익숙하지 않다면, SQLite 문서가 랭귀지를 설명하고 있습니다.

https://sqlite.org/lang.html

 

데이터베이스에 연결

 

첫째로 SQLite 데이터베이스와 일할 때 해야할 것은(그리고 다른 파이썬 데이터베이스 라이브러리들과) 이것에 대한 연결을 생성하는 것입니다.

어떤 쿼리들과 연산들도 작업이 마쳐진 후에 닫혀지는 연결을 통해 수행됩니다.

웹 어플리케이션들에서는 이 연결은 일반적으로 요청에 묶여있습니다. 이것은 요청이 처리될때(핸들링 될떄)와 같은 포인트에서 생성됩니다, 그리고 응답이 보내지기 전에 닫힙니다.

 

flaskr/db.py

 

import sqlite3

 

import click

from flask import current_app, g

from flask.cli import with_appcontext

 

def get_db():

if ‘db’ not in g:

g.db = sqlite3.connect(

current_app.config[‘DATABASE’],

detect_types = sqlite3.PARSE_DECLTYPES

)

g.db.row_factory = sqlite3.Row

 

return g.db

 

def close_db(e=None):

db = g.pop(‘db’, None)

 

if db is not None:

db.close()

 

g는 각 요청을 위한 특별한 객체입니다. 이것은 요청동안 여러 함수들에 의해 접근될 수 있는 데이터를 저장하기 위해 사용됩니다. 만약 get_db가 동시 요청에 두번째로 불려진다면 연결은 저장되고 새로운 연결을 생성하는 대신 재사용 됩니다.

 

Current_app은 플라스크 어플리케이션을 향하는 요청을 처리하는 다른 특별한 객체입니다. 당신은 어플리케이션 factory를 사용했었기 때문에, 당신의 나머지 코드를 작성할때 다른 어플리케이션 객체가 존재하지 않습니다. get_db는 어플리케이션이 생성되고 요청이 처리될때 호출될 것이고, 따라서 current_app은 사용될 수 있습니다.

 

Sqlite3.connect()는 데이터베이스 구성 키를 향하는 파일을 향한 연결을 설립합니다. 이 파일은 아직 존재하지 않지만, 추후 당신이 데이터베이스를 시작하게될때는 존재하게 될 것입니다.

 

sqlite3.Row는 dicts처럼 행동하는 rows들을 리턴받는 연결을 말합니다. 이것은 name을 통한 columns들에 대한 접근을 허용합니다.

 

close_db는 연결이 g.db가 설정된 것에 생성되었는지 확인합니다. 만약 연결이 존재한다면, 이것을 닫습니다. 게다가 당신은 당신의 어플리케이션에 어플리케이션 factory 안에서 close_db 함수에 대해 언급하며 각 요청 이후 이것이 불려지도록 하게 합니다.

 

테이블들 생성

 

SQLite에서, 데이터는  tables들과 columns에 저장됩니다. 이것들은 당신이 데이터를 저장하고 이끌어내기 전에 생성될 필요가 있습니다. Flaskr은 user 테이블에 users들을 저장할 것이고, post 테이블에 post들을 저장할 것입니다. 빈 테이블들을 생성하기 위한 SQL 명령어들을 가지는 파일을 생성하세요.

 

DROP TABLE IF EXISTS user;

DROP TABLE IF EXISTS post;

 

CREATE TABLE user(

id INTEGER PRIMARY KEY AUTOINCREMENT,

username TEXT UNIQUE NOT NULL,

password TEXT NOT NULL

);

 

CREATE TABLE post(

id INTEGER PRIMARY KEY AUTOINCREMENT,

author_id INTEGER NOT NULL,

created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

title TEXT NOT NULL,

body TEXT NOT NULL,

FOREIGN KEY (author_id) REFERENCES user(id)

);

 

db.py 파일에 이러한 SQL 명령어들을 실행할 파이썬 함수들을 추가하세요.

 

 Flask/db.py

 

def init_db():

db = get_db()

 

with current_app.open_resource(‘schema.sql’) as f:

db.executescript(f.read().decode(‘utf8’))

 

@click.command(‘init-db’)

@with_appcontext

def init_db_command():

“””Clear the existing data and create new tables.”””

init_db()

click.echo(‘Initialized the database.’)

 

Open_resource()는 추후에 어플리케이션이 배포될때 당신이 위치가 어디인지 반드시 알 필요가 없기 때문에 유용합니다, 즉 flaskr 패키지에 상대적인 파일을 엽니다. get_db는 파일로부터 명령어들을 읽어 이를 수행하도록 사용되어 데이터베이스 연결을 리턴합니다.

 

click.command()는 command line 에서의 init-db 라는 명렁어를 정의합니다. 이 명령어는 init-db 함수를 호출하고 사용자에게 성공 메시지를 보여줍니다. 당신은 명렁어 작성에 대하 더 많은 것을 배울 수 있는 Command Line Interface를 읽을 수 있습니다. https://flask.palletsprojects.com/en/2.0.x/cli/

 

 

어플리케이션 등록하기.

close_db와 init_db_command 함수들은 어플리케이션 instance에 등록될 필요가 있습니다. 그렇지않으면 그들은 어플리케이션에 의해 사용될 수 없을 것입니다. 그러나, 당신이 factory 함수를 사용하고 있기 대문에, 이러한 instance들은 함수들을 작성할 때 이용할 수 없습니다. 대신, 어플리케이션을 가지고 등록을 수행하는 함수를 작성합니다.

 

flaskr/db.py

def init_app(app):

app.teardown_appcontext(close_db)

app.cli.add_command(init_db_command)

 

app.teardown_appcontext() 는 응답이 리턴된 후에 클리닝 업 될때 플라스크에게 함수를 호출하라 요청합니다.

(-요청마다 실행된다고 합니다.

https://flask.palletsprojects.com/en/0.12.x/appcontext/#app-context

 

Context Usage

context 는 전형적으로 사용 경우 혹은 요청마다 생성될 필요가 있을 때 자원을 캐시하기 위해 사용됩니다. 예를 들어, 데이터베이스 연결들은 그곳에 가기 위해 운명지어져 있습니다. 어플리케이션 콘텍스트에 무엇인가들을 저장할때 유니크 이름들은 플라스크 어플리케이션과 익스텐션들 사이에서 공유 될 수 있는 이 장소로 선택되어져야 합니다.

 

가장 흔한 사용은자원 관리를 분할하기 위해 두가지로 나뉩니다.

  1. 콘텍스트에서 암시적인 자원 캐싱
  2. 자원 할당해제를 기반으로 한 콘텍스트 티어다운

 

 

일반적으로 get_X()  함수는 만약 아직 존재하지 않으면 자원 X를 생성하거나 그렇지않다면 같은 자원을 반환합니다, 그리고 teardown_X() 함수는 teardown 핸들러로 등록됩니다.

 

여기 데이터베이스에 연결된 예시가 있습니다.

)

 

 

App.cli.add_command() 는 플라스크 명렁어에 호출될 수 있는 새로운 명령어를 추가합니다.

 

팩토리로부터 이 함수를 import 하고 호출하세요. 새로운 코드를 app이 리턴되기 전에 팩토리 함수의 끝에 위치시키세요.

 

flaskr/__init__.py

 

def create_app():

app = ….

#exisiting code omitted

 

from . import db

db.init_app(app)

 

return app

 

데이터베이스 파일 초기화하기

 

이제 init-db는 app에 등록되었습니다, 이것은 flask 명령어를 통해 호출될 수 있습니다, 이전 페이지의 run 명령어와 유사합니다.

 

노트:

만약 당신이 이전페이지에서 서버를 실행 중이라면, 당신은 서버를 중단시킬 수 있습니다, 또른 새로운 터미널에서 이 명령어를 실행시킬 수 있습니다. 만약 당신이 새로운 터미널을 사용한다면, 당신의 프로젝트 경로를 변경하는 것을 기억하고 Installation에 설명된 것처럼 env 를 활성화 시키는 것을 기억하세요. 당신은 또한 Flask_APP과 FLASK_ENV를 이전 페이지에서 보여진 것처럼 설정할 필요가 있습니다.

 

Init-db 명령어를 실행시키세요.

 

flask init-db

 

이제 당신의 프로젝트 안의 instance 폴더 내에는 flaskr.sqlite 파일이 존재할 것입니다.