📝 RDB

데이터베이스(DataBase)의 종류는 크게 1. 관계형 데이터베이스(RDB, 2. NoSQL(Not Only SQL)로 나뉜다.

RDB(Relation Database)는 관계형 데이터 모델을 기반으로 한 데이터 베이스다.
다시 말해, 키(Key) - 값(Value)들의 간단한 관계를 테이블화한 데이터베이스다. RDB는 다음 특징을 가진다.

  • 데이터 독립성이 높다.
  • 고수준의 DML을 사용해서, 결합, 제양, 투영 등의 관계 조작에 의해 비약적으로 표현 능력을 높일 수 있다.
  • 이들의 관계 조작에 의해 자유롭게 구조를 변경할 수 있다.

💡 RDB의 종류

  • Oracle
  • MySQL
  • MS-SQL
  • DB2
  • Maria DB
  • Derby
  • SQLite

 

📝 RDB와 Flask의 상호작용

Flask에서 RDB를 연동하면 어떻게 될까 ? Flask에서 입력 받은 내용들을 DB에 저장할 수 있어야 한다.

= 효율적인 데이터 관리 기능 제공

파이썬은 오픈 소스와 상용 데이터베이스에 대한 대부분의 데이터베이스 엔진을 위한 패키지를 가지고 있다.
앞으로의 포스팅에서는 그 중, sqlite3 와 Flask 어플리케이션 안에 있는 SQLAlchemy를 사용해서 진행한다.

SQLAlchemy파이썬 코드에 DB와 연결하기 위해 사용되는 라이브러리다.

[ 출처 : elice ]

 

📝 Flask - RDB 예제 : 게시판 구현하기

💡 DB 사용자 추가

from flask import Flask, render_template, request, url_for, redirect
import sqlite3 # salite3

app = Flask(__name__)
conn = sqlite3.connect("database.db")   # splite3 db 연결
print("Opened database successfully")
conn.execute("CREATE TABLE IF NOT EXISTS Board(name TEXT, context TEXT)")   # Board 라는 DB생성
print("TABLE Created Successfully")
name = [
    ["Elice", 15],
    ["Dodo", 16],
    ["checher", 17],
    ["Queen", 18]
]
for i in range(len(name)):
    conn.execute(f"INSERT INTO Board(name,context) VALUES('{name[i][0]}', '{name[i][1]}')")  # Board DB에 데이터 삽입
conn.commit()   # 지금껏 작성한 SQL, DB에 반영 commit
conn.close()    # 작성 다한 DB는 닫아줘야함 close

# ================= 여기서부터는 다시 Flask 영역 ==========================

@app.route('/')
def board():
    con = sqlite3.connect("database.db")
    cur = con.cursor()
    cur.execute("SELECT * FROM Board")
    rows = cur.fetchall()

    print("DB: ")
    for i in range(len(rows)):
        print(rows[i][0] + ':' + rows[i][1])
    return render_template("board1.html", rows = rows)


@app.route("/search", methods=["GET","POST"])
def search():
    if request.method == "POST":
        name = request.form["name"] # search.html 가보면, form에 name만 받기로 함.
        con = sqlite3.connect("database.db")
        cur = con.cursor()
        cur.execute(f"SELECT * FROM Board WHERE name='{name}'")
        rows = cur.fetchall()
        print("DB : ")
        for i in range(len(rows)):
            print(rows[i][0] + ':' + rows[i][1])
        return render_template("search.html", rows=rows)
    else:
        return render_template("search.html")

@app.route("/add", methods=["GET","POST"])
def add():
    if request.method == "POST":
        try:
            name = request.form["name"]
            context = request.form["context"]

            # DB에 접근해서, 데이터를 삽입할때는, 직접 DB를 열어야되는데, 윗 과정처럼, close까지 하기 힘드니깐, 하는 방식, 결과는 같은 것 !
            with sqlite3.connect("database.db") as con:
                cur = con.cursor()
                cur.execute(f"INSERT INTO Board(name,context) VALUES('{name}','{context}')")
                con.commit()
        except:
            con.rollback()  # DB 롤백함수, SQL이 오류나면, 반영전, 이전 상태로 돌리는 것
        finally:
            return redirect(url_for("board"))
    else:
        return render_template("add.html")


if __name__ == '__main__':
    app.run()
<!-- ./templates/board1.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4><a href="{{url_for('add')}}">추가</a> <a href="{{url_for('search')}}">검색</a><br><br>목록</h4>
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
        </thead>
        {% for row in rows %}
        <tr>
            <td>{{ row[0] }}</td>
            <td>{{ row[1] }}</td>
        </tr>
        {% endfor %}
    </table>
</body>

</html>
<!-- ./templates/add.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4>추가</h4>
    <form action="/add" method="POST">
        이름<br>
        <input type="text" name="name" /><br>
        내용<br>
        <input type="text" name="context" style="text-align:center; width:400px; height:100px;" /><br><br>
        <input type="submit" value="게 시" /><br>
    </form>
</body>

</html>
<!-- ./templates/search.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <form action="/search" method="POST">
        <input type="text" name="name" />
        <input type="submit" value="검 색" /><br>
    </form>
    <h4>검색결과</h4>
    {% if rows%}
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
        </thead>
        {% for row in rows %}
        <tr>
            <td>{{ row[0] }}</td>
            <td>{{ row[1] }}</td>
        </tr>
        {% endfor %}
        {% else %}
        <p> 검색결과가 없습니다. </p>
        {% endif %}
    </table>
</body>

</html>

[ 출처 : elice ]

 

💡 중복 사용자 제어 ( 위에, DB 사용자 추가에서 변한 코드는 몇 없음

from flask import Flask, render_template, request, url_for, redirect
import sqlite3 # salite3

app = Flask(__name__)
conn = sqlite3.connect("database.db")   # splite3 db 연결
print("Opened database successfully")
conn.execute("CREATE TABLE IF NOT EXISTS Board(name TEXT, context TEXT)")   # Board 라는 DB생성
print("TABLE Created Successfully")
name = [
    ["Elice", 15],
    ["Dodo", 16],
    ["checher", 17],
    ["Queen", 18]
]
for i in range(len(name)):
    conn.execute(f"INSERT INTO Board(name,context) VALUES('{name[i][0]}', '{name[i][1]}')")  # Board DB에 데이터 삽입
conn.commit()   # 지금껏 작성한 SQL, DB에 반영 commit
conn.close()    # 작성 다한 DB는 닫아줘야함 close

# ================= 여기서부터는 다시 Flask 영역 ==========================

@app.route('/')
def board():
    con = sqlite3.connect("database.db")
    cur = con.cursor()
    cur.execute("SELECT * FROM Board")
    rows = cur.fetchall()

    print("DB: ")
    for i in range(len(rows)):
        print(rows[i][0] + ':' + rows[i][1])
    return render_template("board1.html", rows = rows)


@app.route("/search", methods=["GET","POST"])
def search():
    if request.method == "POST":
        name = request.form["name"] # search.html 가보면, form에 name만 받기로 함.
        con = sqlite3.connect("database.db")
        cur = con.cursor()
        cur.execute(f"SELECT * FROM Board WHERE name='{name}'")
        rows = cur.fetchall()
        print("DB : ")
        for i in range(len(rows)):
            print(rows[i][0] + ':' + rows[i][1])
        return render_template("search.html", rows=rows)
    else:
        return render_template("search.html", msg ="검색어를 입력해주세요.")

@app.route("/add", methods=["GET","POST"])
def add():
    if request.method == "POST":

        name = request.form["name"]
        context = request.form["context"]

        # DB에 접근해서, 데이터를 삽입할때는, 직접 DB를 열어야되는데, 윗 과정처럼, close까지 하기 힘드니깐, 하는 방식, 결과는 같은 것 !
        with sqlite3.connect("database.db") as con:
            cur = con.cursor()
            cur.execute(f"SELECT count(*) FROM Board WHERE name='{name}'")
            
            # 회원 한명, 추가할라 했는데, 그전에 들어온, name값이랑 같은 이름이 DB에 있으면, 중복회원자이므로, 못하게 제어함
            if cur.fetchall()[0][0] == 0:   # 중복이름이 없으면
                cur.execute(f"INSERT INTO Board(name,context) VALUES('{name}','{context}')")
                con.commit()
                cur.execute("SELECT * FROM Board")
                rows = cur.fetchall()
                return render_template("board1.html",rows= rows)        
            else:   # 중복이름이 있으면
                return render_template("add.html",msg = "중복사용자가 있습니다.")
    else:
        return render_template("add.html")


if __name__ == '__main__':
    app.run()
<!-- ./templates/board1.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4><a href="{{url_for('add')}}">추가</a> <a href="{{url_for('search')}}">검색</a><br><br>목록</h4>
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
        </thead>
        {% for row in rows %}
        <tr>
            <td>{{ row[0] }}</td>
            <td>{{ row[1] }}</td>
        </tr>
        {% endfor %}
    </table>
</body>

</html>
<!-- ./templates/add.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4>추가</h4>
    <form action="/add" method="POST">
        이름<br>
        <input type="text" name="name" /><br>
        내용<br>
        <input type="text" name="context" style="text-align:center; width:400px; height:100px;" /><br><br>
        <input type="submit" value="게 시" /><br>
    </form>
    {% if msg %}
    <p> {{ msg }} </p>
    {% endif %}
</body>

</html>
<!-- ./templates/reaserch.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <form action="/search" method="POST">
        <input type="text" name="name" />
        <input type="submit" value="검 색" /><br>
    </form>
    <h4>검색결과</h4>
    {% if rows%}
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
        </thead>
        {% for row in rows %}
        <tr>
            <td>{{ row[0] }}</td>
            <td>{{ row[1] }}</td>
        </tr>
        {% endfor %}
        {% elif msg %}
        <p> {{ msg }} </p>
        {% else %}
        <p> 검색결과가 없습니다. </p>
        {% endif %}
    </table>
</body>

</html>

[ 출처 : elice ]

 

💡 게시판 내용 생성 및 조회

위에서, DB 사용자 생성, 중복제거 내용과 동일

 

💡 게시판 내용 수정 및 삭제

#DATABASE
from flask import Flask, render_template, request, url_for, redirect
import sqlite3
app = Flask(__name__)
conn = sqlite3.connect('database.db')
print ("Opened database successfully")
conn.execute("DROP TABLE IF EXISTS Board")  # Board 테이블이 기존에 있다면 삭제 (매번, 동일한 파일에서 실행하면, 내용이 겹쳐서 만듦)
conn.execute('CREATE TABLE IF NOT EXISTS Board (name TEXT, context TEXT)')  # Board 테이블이 기존에 없다면 생성
print ("Table created successfully")
name = [['Elice', 15], ['Dodo', 16], ['Checher', 17], ['Queen', 18]]
for i in range(4):
    conn.execute(f"INSERT INTO Board(name, context) VALUES('{name[i][0]}', '{name[i][1]}')")
conn.commit()
conn.close()

# root = home
@app.route('/')
def board():
    con = sqlite3.connect("database.db")
    cur = con.cursor()
    cur.execute("select * from Board")
    rows = cur.fetchall()
    print("DB:")
    for i in range(len(rows)):
            print(rows[i][0] + ':' + rows[i][1])
    return render_template('board1.html', rows = rows)

# 게시물 조회 (Read)
@app.route('/search', methods = ['GET', 'POST'])
def search():
    if request.method == 'POST':
        name = request.form['name']
        con = sqlite3.connect("database.db")
        cur = con.cursor()
        cur.execute(f"SELECT * FROM Board WHERE name='{name}' or context='{name}'")
        rows = cur.fetchall()
        print("DB:")
        for i in range(len(rows)):
            print(rows[i][0] + ':' + rows[i][1])
        return render_template('search.html', rows = rows)
    else:
        return render_template('search.html')

# 게시물 생성 (Create)
@app.route('/add', methods = ['GET', 'POST'])
def add():
    if request.method == 'POST':
        try:
            name = request.form['name']
            context = request.form['context']
            with sqlite3.connect("database.db") as con:
                cur = con.cursor()
                cur.execute(f"INSERT INTO Board (name, context) VALUES ('{name}', '{context}')")
                con.commit()
        except:
            con.rollback()
        finally : 
            con.close()
            return redirect(url_for('board'))
    else:
        return render_template('add.html')
# 위에 조회, 생성은 이전과 동일 

# 게시물 내용 갱신(Update)
@app.route("/update/<uid>", methods=["GET","POST"])
def update(uid):
    if request.method == "POST":
        name = request.form["name"]
        context = request.form["context"]
        
        # 내용 갱신하고
        with sqlite3.connect("database.db") as con:
            cur = con.cursor()  # connection한 db에 접근하기 위해, cursor 객체 만들기
            cur.execute(f"UPDATE Board SET name='{name}', context='{context}' WHERE name='{uid}'")
            con.commit()

        return redirect(url_for("board"))   # 갱신되었는지, board함수 리다이렉트해서, / 페이지 렌더링
    else:
        con = sqlite3.connect("database.db")
        cur = con.cursor()
        cur.execute(f"SELECT * FROM Board WHERE name='{uid}'")
        row = cur.fetchall()
        return render_template("update.html",row=row)

@app.route("/delete/<uid>")
def delete(uid):
    # 들어온 uid 값이랑 name이랑 delete 연산하고 반영
    with sqlite3.connect("database.db") as con:
        cur = con.cursor()
        cur.execute(f"DELETE FROM Board WHERE name='{uid}'")
        con.commit()

    return redirect(url_for('board'))  # 삭제 반영하고, 반영됬는지, board함수 리다이렉트, / 페이지 렌더링

if __name__ == '__main__':
    app.run()
<!-- ./templates/board1.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4><a href="{{url_for('add')}}">추가</a> <a href="{{url_for('search')}}">검색</a><br><br>목록</h4>
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
            <td>수정/삭제</td>
        </thead>
        {% for row in rows %}
        <tr>
            <td>{{ row[0] }}</td>
            <td>{{ row[1] }}</td>
            <td><a href="{{url_for('update', uid = row[0])}}">수정</a> <a
                    href="{{url_for('delete', uid = row[0])}}">삭제</a></td>
        </tr>
        {% endfor %}
    </table>
</body>

</html>
<!-- ./templates/add.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4>추가</h4>
    <form action="/add" method="POST">
        이름<br>
        <input type="text" name="name" /><br>
        내용<br>
        <input type="text" name="context" style="text-align:center; width:400px; height:100px;" /><br><br>
        <input type="submit" value="게 시" /><br>
    </form>
</body>

</html>
<!-- ./templates/research.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <form action="/search" method="POST">
        <input type="text" name="name" />
        <input type="submit" value="검 색" /><br>
    </form>
    <h4>검색결과</h4>
    {% if rows%}
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
        </thead>
        {% for row in rows %}
        <tr>
            <td>{{ row[0] }}</td>
            <td>{{ row[1] }}</td>
        </tr>
        {% endfor %}
        {% else %}
        <p> 검색결과가 없습니다. </p>
        {% endif %}
    </table>
</body>

</html>
<!-- ./templates/update.html -->

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>SQLite3 게시판 등록</title>

    <style type="text/css">
        body {
            text-align: center;
        }
    </style>
</head>

<body>
    <h3>게시판</h3>
    <h4>수정</h4>
    <form action="" method="POST">
        이름<br>
        <input type="text" name="name" /><br>
        내용<br>
        <input type="text" name="context" style="text-align:center; width:400px; height:100px;" /><br><br>
        <input type="submit" value="수 정" /><br>
    </form>
    <h4>기존</h4>
    <table border=1 width="600" align="center">
        <thead>
            <td>이름</td>
            <td>내용</td>
        </thead>
        <tr>
            <td>{{ row[0][0] }}</td>
            <td>{{ row[0][1] }}</td>
        </tr>
    </table>
</body>

</html>

[ 출처 : elice ]

 

728x90
반응형

+ Recent posts