티스토리 뷰

728x90

DB에 데이터 저장하고 불러오기를 배웠으니 이제 우리 Flask 프로젝트에서 브라우저에서 사용자가 입력한 데이터를 받아 DB에 저장을 해보죠.

먼저 이전 글에서 db 사용 하는 소스들을 함수로 만들어서 필요한 함수를 불러서 사용 하도록 해봅니다.

저는 dbdb.py 라는 파일을 생성 했습니다.

그리고 지난 글에서 사용 했던 소스를 조금 변경 해서 각각 쪼개어 함수로 만듭니다.

import sqlite3

def dbcon():
    return sqlite3.connect('mydb.db')

db 파일 접속 함수 입니다.

다른 DB를 옮겨도 사용할 수 있게 테이블을 생성하는 함수도 따로 생성 해놓습니다. 

테이블이 이미 있다면 새로 생성되지 않고 except 가 됩니다.

def create_table():
    try:
        db = dbcon()
        c = db.cursor()
        c.execute("CREATE TABLE student (num varchar(50), name varchar(50))")
        db.commit()
    except Exception as e:
        print('db error:', e)
    finally:
        db.close()

 

이제 데이터를 넣는 함수 입니다.

def insert_data(num, name):
    try:
        db = dbcon()
        c = db.cursor()
        setdata = (num, name)
        c.execute("INSERT INTO student VALUES (?, ?)", setdata)
        db.commit()
    except Exception as e:
        print('db error:', e)
    finally:
        db.close()

전체 데이터를 보는 함수 입니다. fetchall() 함수는 select 쿼리의 모든 데이터를 가져 와서 리스트로 반환 합니다.

번호와 이름의 데이터들을 튜플로 받아와 리스트(list) 담고 그 튜플이 담긴 리스트를 반환 합니다. 

def select_all():
    ret = list()
    try:
        db = dbcon()
        c = db.cursor()
        c.execute('SELECT * FROM student')
        ret = c.fetchall()
    except Exception as e:
        print('db error:', e)
    finally:
        db.close()
        return ret

마지막으로 학번으로 데이터를 검색 해서 가져 오는 함수 입니다.  fetchone() 함수는 하나의 데이터를 반환 합니다. 데이터가 없을 때에는 None을 반환합니다. 아래 코드를 실행 하면 번호와 이름이 튜플에 데이터가 담겨 반환 됩니다.

def select_num(num):
    ret = ()
    try:
        db = dbcon()
        c = db.cursor()
        setdata = (num,)
        c.execute('SELECT * FROM student WHERE num = ?', setdata)
        ret = c.fetchone()
    except Exception as e:
        print('db error:', e)
    finally:
        db.close()
        return ret

이제 app.py 에 저 dbdb.py 를 포함 시키고 기존에 POST로 넘어오는 데이터를 파일에 저장 하던 방식을 DB에 저장 하는 방식으로 변경 해봅니다.

이전 글 소스를 참고

[웹 앱프로그래밍] 파이썬 플라스크(Python Flask) 파일 입출력을 이용해서 데이터 저장

 

위 소스를 이렇게 변경 합니다. 먼저 import dbdb 를 추가 하고 method() 함수내에 파일에 저장 하던 부분을 지우고 

dbdb.insert_data(num, name) 를 추가 합니다. 그리고 파일 읽어 오는 함수 getinfo()도 파일 읽기 부분을 지우고

info = dbdb.select_all() 를 넣고 info 정보로 화면에 잘 출력 해봅니다.

아래는 변경된 전체 소스 입니다.

from flask import Flask, request, render_template, redirect, url_for, abort
import dbdb

app = Flask(__name__)

@app.route('/form')
def form():
    return render_template('test.html')

@app.route('/method', methods=['GET', 'POST'])
def method():
    if request.method == 'GET':
        return 'GET 으로 전송이다.'
    else:
        num = request.form["num"]
        name = request.form["name"]
        dbdb.insert_data(num, name)
        return 'POST 이다. 학번은: {} 이름은: {}'.format(num, name)

@app.route('/getinfo')
def getinfo():
    info = dbdb.select_all()
    retstr = ''
    for i, v in enumerate(info):
        retstr += '%d. 학번: %s 이름: %s<br>' % (i+1, v[0], v[1])
    return retstr

index값을 받기 위해 enumerate 를 사용 했습니다. 돌려 보면 잘 돌아 가는 것을 볼 수 있습니다.

여기서 getinfo 의 경우 꾸역 꾸역 문자열로 변경 시켜 return으로 화면 html 형식으로 출력 을 했는데 아주 불편하고 소스도 지저분 하고 보기도 안좋습니다.

이 info 리스트 변수를 html 에 전달해서 html에서 그나마 조금 이쁘게(?) 출력이 되게끔 만들어 봅시다. 이미 눈치를 챈 분들은 render_template으로 html을 부르고 리스트 변수를 전달해서 Jinja2 템플릿 엔진에서 해주겠구나라고 생각할 수 있겠죠.

이제 끝을 향해 달려 가고 있습니다. 조금만 더 힘내서 달려 봅시닷!!

 

꾸역 꾸역 문자열로 변경 시켜 return으로 화면 html 형식으로 출력 을 했는데 아주 불편하고 소스도 지저분 하고 보기도 안좋다고 했습니다. 저만 그렇게 느끼지는 않을거라 생각합니다.

데이터베이스의 정보를 HTML 파일에 보내어서 그나마 이쁘게 출력 해봅시다. 이제 Jinja2 템플릿 엔진을 이용 해야 합니다. 먼저 data 를 전달 하는 부분은 render_template 에서 html  을 부를 때 파라미터(인자)로 같이 넘겨 주면 됩니다.

render_template(html파일, 전달 데이터) 이렇게 말이죠.

이전 소스를 조금 바꿔서 데이터를 전달 해 봅니다.

 

@app.route('/getinfo')
def getinfo():
    info = dbdb.select_all()
    return render_template("info.html", data=info)

억지로 문자열을 만들고 html 형식으로 return 을 해주는 것을  render_template 으로 html  파일을 불러 data 변수 이름으로 info 의 값을 담아 전달 해줍니다. 이제 html 에서 저 data 변수 이름으로 info 값을 받아 출력을 해봅니다. jinja2 문법을 사용 해야 합니다. 여기서 중요한 것은 변수명을 지정해서 보내 줘야 합니다. info의 값은 db에서 받은 값이고 data 변수에 대입을 시켜 전달 합니다. 물론 꼭 data 일 필요는 없습니다만 여기서는 data 로 지정 했습니다.

info=info 이렇게도 무방합니다.

info 는 리스트(list) 이기 때문에 이 전 글에서도 for 문을 사용 해서 데이터들을 출력 했습니다. html로 전달된 info 도 리스트 이기 때문에 html 파일 내에 Jinja2 문법을 활용 하여 for loop 로 출력을 해야 합니다. html 에 보낼때 변수 이름을 data 로 했기 때문에 for문에서 리스트 변수는 info가 아닌 data 가 된다는 것을 유의 해서 코드를 작성 합니다.

코드는 아래와 같이 작성합니다.

<!DOCTYPE html>
<html>
<body>
<h2>학생 정보 출력</h2>
{% for i in data %}
학번: {{ i[0] }} <br>
이름: {{ i[1] }} <br>
{% endfor %}
</body>
</html>

위에서 i[0] 으로 접근 한 이유는 data는 리스트이고 리스트가 담고 있는 데이터는 튜플이기 때문에 튜플에 담겨 있는 데이터 내용은 (학번, 이름) 으로 되어 있기 때문에 i[0] 은 학번이 되고  i[1] 은 이름이 됩니다.

만약 for 문 안에 index 숫자를 붙여 주고 싶다면  {{ loop.index }} 를 사용 하면 됩니다.

이런식이 되겠네요.

<!DOCTYPE html>
<html>
<body>
<h2>학생 정보 출력</h2>
{% for i in data %}
{{ loop.index }}. 
학번: {{ i[0] }} <br>
이름: {{ i[1] }} <br>
{% endfor %}
</body>
</html>

출력을 어떻게 하느냐는 디자인 부분이기 때문에 이쁘게 출력을 해보도록 합니다. (테이블을 이용한다던가...)

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함