Python+Flask에서 SQLite 사용해 보기

Python+Flask에서 SQLite를 사용해 보고 정리해 봤습니다.
2021.09.11

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 Python+Flask에서 SQLite를 사용해 봤습니다.

SQLite란?

SQLite는 작고, 빠르고, 자주적이며, 안정성이 높고, 완전한 기능을 갖춘 SQL 데이터베이스 엔진을 구현하는 C언어 라이브러리입니다. SQLite는 세계에서 가장 많이 사용되는 데이터베이스 엔진입니다. SQLite는 모든 휴대폰과 대부분의 컴퓨터에 내장되어 있으며 사람들이 매일 사용하는 수많은 다른 애플리케이션 안에 번들되어 있습니다.

사실상 SQLite의 장점은 서버를 설치할 필요 없이, 편리하게 사용할 수 있다는 점이 가장 큰 장점이 아닌가 생각합니다.

Flask에서 SQLite Create

import sqlite3

먼저 SQLite를 사용하기 위해서 import sqlite3를 입력합니다. Python에서는 기본적으로 SQLite 모듈이 설치되어 있기 때문에, 따로 설치할 필요는 없습니다.

conn = sqlite3.connect('database.db')

이어서 다음 명령어로 database.db 데이터베이스에 SQLite DB를 연결 합니다.

conn.execute(
'''
create table users (email text, name text)
'''
)

다음은 테이블을 생성하는 명령어입니다. 간단하게 email과 name 컬럼을 가지고 있는 테이블을 생성합니다.

import sqlite3

conn = sqlite3.connect('database.db')
print('create & connect database')

conn.execute(
'''
create table users (email text, name text)
'''
)
print('create table')

conn.close()

다음 코드로 데이터베이스와 테이블을 생성해 봅시다.

create & connect database
create table

그럼 데이터베이스 생성과 테이블이 생성 됐다는 메시지가 출력 됩니다.

VS Code에서 확인해 보면, dtabase.db가 생성된 것을 확인할 수 있습니다.

Flask에서 HTML 페이지 열기

이제 데이터베이스와 테이블을 생성했으니, 테이블에 데이터를 넣어보도록 하겠습니다. 우선 그 전에 데이터를 넣을 html 폼을 만들 필요가 있기 때문에 템플릿 이라는 기능에 대해서 살펴보고 넘어가겠습니다.

Flask에서는 보여지는 부분과 처리하는 부분을 나누기 위해 템플릿이라는 기능을 제공합니다. 템플릿에 사용되는 파일들은

  • templates
디렉토리에 저장되며 일반적으로 .html 파일을 사용합니다.
from flask import Flask, render_template

templates을 사용하기 위해서는, render_template을 import 합니다.

@app.route('/')
def home():
return render_template('index.html')

def home이라는 함수에서 index.html을 리턴하고 있습니다. 즉 '/' 경로로 접속하면 index.html이 출력됩니다.

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/')
def home():
return render_template('index.html')

app.py의 코드입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>home</title>
</head>
<body>
    <h1>Home</h1>
</body>
</html>

이어서 templates 디렉토리에 있는 index.html 파일 소스코드 입니다. index.html 페이지가 잘 나오는 것을 볼 수 있습니다.

HTML 페이지 구성

  • index.html
  • list.html
  • result.html
  • user.html

위에서 언급한 템플릿을 바탕으로 4개의 HTML 페이지를 구성해 보도록 하겠습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>home</title>
</head>
<body>
    <h1>Home</h1>
</body>
</html>

index.html 입니다.

<!doctype html>
<html>
   <body>
      <table border = 1>
         <thead>
            <td>Email</td>
            <td>Name</td>
         </thead>

         {% for row in rows %}
            <tr>
               <td>{{row["email"]}}</td>
               <td>{{row["name"]}}</td>
            </tr>
         {% endfor %}
      </table>
   </body>
</html>

list.html 입니다. 테이블에서 전달 받은 값을 출력하는 페이지입니다.

<!doctype html>
<html>
   <body>
       result : {{ msg }}
   </body>
</html>

reult.html 입니다. 테이블에 성공적으로 데이터가 들어갔는지 확인하기 위한 페이지입니다. msg를 전달 받아서 결과 값을 출력합니다.

<html>
   <body>
      <form action = "{{ url_for('user_info') }}" method = "POST">
         <h3>User Information</h3>
         Email<br>
         <input type = "text" name = "user_email" /></br>

         Name<br>
         <textarea name = "user_name" ></textarea><br>
         <input type = "submit" value = "submit" /><br>
      </form>
   </body>
</html>

마지막으로 user.html 입니다. 유저의 이메일과 이름을 입력하고 결과 값을 user_info로 넘겨줍니다.

app.py 구성

from flask import Flask, render_template, request
import sqlite3 as sql
app = Flask(__name__)

@app.route('/')
def home():
return render_template('index.html')

@app.route('/user_form')
def new_user():
return render_template('user.html')

먼저 메인 페이지는 index.html 이기 때문에, / 경로로 들어가게 되면 index.html가 출력되게 했습니다. 마찬가지로 유저 데이터를 입력하는 페이지는 /user_form 경로로 들어가게 되면 user.html이 출력되게 했습니다.

@app.route('/user_info',methods = ['POST', 'GET'])
def user_info():
if request.method == 'POST':
try:
user_email = request.form['user_email']
user_name = request.form['user_name']

with sql.connect("database.db") as con:
cur = con.cursor()

cur.execute("INSERT INTO users (email, name) VALUES (?,?)",(user_email,user_name) )

msg = "Success"

except:
con.rollback()
msg = "error"

finally:
return render_template("result.html",msg = msg)
con.close()

이어서 user_info() 입니다. 먼저 methods = ['POST', 'GET']로 user.html에서 입력한 데이터들을 받아옵니다. if request.method == 'POST': 라는 조건문을 통해 만약 데이터를 받아 왔다면 try를 실행 시킵니다.

cur = con.cursor()의 경우 cursor 클래스는 실질적으로 데이터베이스에 SQL 쿼리를 수행하고, 조회된 결과를 가지고 오는 역할을 합니다. cur.execute로 inser into 문을 실행 합니다. 마지막으로 finally에서는 위에서 데이터에 값이 제대로 처리 되었는지 확인하기 위해서 msg에 Success와 error을 넣었는데, 이 msg값을 result.html로 넘기고 데이터베이스를 닫습니다.

@app.route('/list')
def list():
con = sql.connect("database.db") #database.db파일에 접근.
con.row_factory = sql.Row

cur = con.cursor()
cur.execute("select * from users")

rows = cur.fetchall();
return render_template("list.html",rows = rows)

다음은 list 페이지 처리입니다. con.row_factory = sql.Row는 값을 지정하여 개별 행을 원하는 Python 타입으로 변환 합니다. 기본적으로 key, value 값으로 변환 됩니다.

이어서 select * from users로 users의 데이터 값들을 불러옵니다. Cursor.fetchall()로 조회된 결과 모두를 리스트형태로 반환합니다. 만약 데이터가 없는 경우, 빈리스트를 반환합니다. 마지막으로 list.html에 rows를 리턴합니다.

SQLite 테스트

먼저 메인 페이지입니다.

/user_form 경로에서 이메일과 이름을 입력하고 submit 버튼을 누릅니다.

그럼 Success 라는 결과값이 리턴됩니다.

마지막으로 /list 경로로 들어가 보면 좀 전에 입력했던 유저 데이터가 성공적으로 불러와 진 것을 볼 수 있습니다.