[Flask] Flask 데이터베이스 정의 및 엑세스

최더디·2020년 9월 2일
0

Flask-문서번역

목록 보기
2/4

해당 글은 공부를 위해 https://flask.palletsprojects.com/en/1.1.x/tutorial/database/ 을 번역한 글입니다.

데이터베이스 정의 및 엑세스


응용 프로그램은 SQLite 데이터베이스를 사용하여 사용자와 게시물을 저장한다.
Python은 sqlite3 모듀에서 SQLite 를 기본적으로 지원한다.

SQLite는 별도의 데이터베이스 서버를 설정할 필요가 없고 Python에 내장되어 있기 때문에 편리하다.
하지만 동시 요청이 동시에 데이터베이스에 쓰려고하면 각각 쓰기가 순차적으로 발생하므로 속도가 느려진다.
작은 응용 프로그램에서는 이를 인식하지 못한다. 일단 커지면 다른 데이터베이스로 전환할 수 있다.

데이터베이스 연결


가장 먼저 해야할 일은 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 은 요청을 처리하는 Flask 애플리케이션을 가리키는 또 다른 특수 객체이다.
Application Factory를 사용했기 때문에, 나머지 코드를 작성할 때 애플리케이션 객체가 없다.
get_db 는 애플리케이션이 생성되고 요청을 처리할 때 호출되므로, current_app 이 사용될 수 있다.

sqlite3.connect() 는 DATABASE 구성 키가 가리키는 파일에 대한 연결을 설정한다.이 파일은 아직 존재하지 않아도 되며 나중에 데이터베이스를 초기화해야 한다.

sqlite3.Row 는 dictionary 처럼 동작하는 행을 반환하도록 연결에 지시한다.이렇게하면 이름으로 열에 엑세스 할 수 있다.

close_db 는 g.db 설정 여부를 확인하여 연결이 생성되었는지 확인한다.연결이 있으면 닫힌다.더 내려가면 각 요청 후에 호출되도록 Application Factory의 close_db의 함수에 대해 애플리케이션에 알려준다.

테이블 생성


SQLite에서 데이터는 table과 column 에 저장된다.
데이터를 저장하고 검색하려면 먼저 생성해야 한다.
Flask는 user 테이블에 사용자를 저장하고 post 테이블을 게시한다.
빈 테이블을 만드는 데 필요한 SQL 명령으로 파일을 만든다.

# flaskr/schema.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)
);

다음 SQL 명령을 실행할 Python 함수를 db.py 파일에 추가한다.

# flaskr/db.py

def init_db():
    db = get_db()
    
    with current_app.open_resource('schema.sql') as f:
        db.executescript(f.read().decode('utf-8'))
        
        
@click.command('init-db')
@with_appcontex
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() 는 init_db 함수를 호출하는 init-db라는 command line 명령을 정의하고, 사용자에게 성공 메시지를 보여준다.

응용 프로그램에 등록 (Register with the Application)


close_db 및 init_db_command 함수는 응용 프로그램 인스턴스에 등록을 해야한다.
그렇지 않으면 응용 프로그램에서 사용되지 않는다.
그러나 Factory 함수를 사용하고 있으므로, 함수를 작성할 때 해당 인스턴스를 사용할 수 없다.
대신 응용 프로그램을 받아 등록하는 함수를 작성해라.

# flaskr/db.py

def init_app(app):
    app.teardown_appcontext(close_db)
    app.cli.add_command(init_db_command)

app.teardown_appcontext()는 응답을 반환한 후 정리할 때 하당 함수를 호출하도록 Flask에 지시한다.
app.cli.add_command() 는 flask 명령으로 호출할 수 있는 새 명령을 추가한다.

# flaskr/__init__.py

def create_app():
    app = ...
    # existing code omitted
    
    from . import db
    db.init_app(app)
    
    return app

Factory에서 이 함수를 가져와서 호출한다. 앱을 반환하기 전에 Factory 함수 끝에 새 코드를 배치한다.

데이터베이스 파일 초기화


이제 init-db 앱에 등록되었으므로 이전 페이지 flask의 run 명령과 유사한 명령을 사용하여 호출할 수 있다.

다음 init-db 명령을 실행해라

$ flask init-db
Initialized the database.

이제 프로젝트 flaskr.sqlite의 instacne 폴더에 파일이 있을 것이다.

profile
focus on why

0개의 댓글