Flask

Flask 이용한 웹사이트 제작기 (3) - DB 연결

sseram 2023. 7. 16. 17:59
반응형

2023.07.15 - [Flask] - Flask 이용한 웹사이트 제작기 (2) - 폴더 구조/ hello world 띄우기

 

Flask 이용한 웹사이트 제작기 (2) - 폴더 구조/ hello world 띄우기

2023.07.10 - [Flask] - Flask 이용한 웹사이트 제작기 (1) - 설치 Flask 이용한 웹사이트 제작기 (1) - 설치 유튭 쇼츠만 죽어라고 내리고 있다보니, 내가 지금 뭘 하고있나.. 라는 자괴감이 들더라. 멍때리

donot-simsim.tistory.com

 

sqlite3 module과 flask 연동.

 


- Connect to the Database

 

공식 듀토리얼에 나와있는 것 처럼, db.py를 만든 후 flask와 연결할 수 있게 준비한다.

 

// flaskr/db.py

import sqlite3

import click
from flask import current_app, g


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라는 이상한 걸 import한다. clean code 관점에서 대체 뭐하는건가... 싶은 함수인디. 밑에 자세히 설명이 나와있는데 대충 읽어 보면.. 한 번 연결해 둔 것을 요청 때마다 끊지 않고, 재사용 할 수 있게끔 도와주는 함수인가보다. 그래서 코드를 보면 처음에 g에 db가 없다면 연결해주고, 있다면 바로 return해준다.

그래서 왜 'g' 라고 한 글자만 써뒀을까.... 좀 풀어서좀 써 주지.

 

current_app은 flask app이 만들어진 후에 생성되는, flask app을 가르키는 또다른 포인터라고 한다. 해당 변수를 통하여 db를 연결한다.

 

 

 

- Create the Tables

 

db를 저장하기 전에 먼저 db의 스키마를 만들어 주자. flaskr은 user table에 user 데이터를 저장해 두고, post table에 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)
);

 

 

그리고 위에서 만들어준 db.py에서, 위의 sql문을 읽어서 실행할 수 있도록 db.py의 close_db 함수 밑에 코드를 추가해주자.

 

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')
def init_db_command():
    """Clear the existing data and create new tables."""
    init_db()
    click.echo('Initialized the database.')

 

이거 보면서, current_app 은 우리가 만든 flaskr 폴더 내부를 기본 route로 사용하는구나, 하고 느꼇다. 해당 폴더 안에 __init__.py 가 있고, 거기서 flask가 생성되어서 그런 걸까.

 

 

click.command('init-db') 는, terminal에서 flask 를 실행할 때 함수를 등록하는 것이라고 한다.

그러니까 저렇게 해 두면,

 

flask --app flaskr init-db

이라고 terminal에서 작성하면 바로 init_db_command를 호출할 수 있다는 말이란다.

 

- Register with the Application

 

위에서 만든 close_db / init_db_command를 등록해 주어야 한다. 여기에서는 __init__.py에서 app을 create할 때, db.py를 import 해 와서 app을 넘겨주고, 해당 app에다가 직접 함수들을 등록하는 방식을 취했다.

 

// flaskr/db.py

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

db.py에 위와 같은 코드를 추가해 주어, teardown 시 close_db 함수를 호출하게 해 주었고

cli에 init_db_command를 추가해 주었다.

 

// flaskr/__init__.py

import os

from flask import Flask

def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        SECRET_KEY='dev',
        DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
    )

	~~~

    from . import db
    db.init_app(app)
    
    
    ~~~~

그리고 위와 같이, flask create_app 시에 db.init_app에 현재 app을 넘겨 주어서 정상적으로 db 초기화가 가능하게 만들었다!

 

 


 

그리고 init_db command를 쳐 보면!

 

 

 

이렇게 flaskr.sqlite가 만들어진다!

 

 

 

2023.07.18 - [Flask] - Flask 이용한 웹사이트 제작기 (4) - auth view code 작성

 

반응형