[개발일지8일차]플라스크 앱에 데이터베이스 연동

1. 학습내용

1) reivew

1-1) flask 실행하는 방법

app = Flask(__name__)
~~
app.run()

1-2) home으로 접근하는 방법

 @app.route('/')

에서 ('/')는 home으로 접근하는 방법이다.

1-3) template() 기능
template() 은 중복을 제거하는 기능이다.

2) Python과 Sqlite 연동하기- 읽기기능

2-1) table에서 아래의 코드를 작성한다.

sqlite3
.open db.sqlite3
CREATE TABLE topics (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
body TEXT
)
;
INSERT INTO topics (title,body) VALUES('SQLite', 'SQLite is ...');

2-2) glitch 상 read.py를 만든다.
file에 read.py 파일 생성

read.py 에서 아래의 코드 작성

import sqlite3
conn = sqlite3.connect('db.sqlite3')
curor = conn.cursor()
curor.execute('SELECT * FROM topics')
topics = curor.fetchall()
print(topics)

이후,

.exit

2-3) table 에서 python3 read.py 입력
결과: 1 SQLite
(1은 id)

3)Python과 Sqlite 연동하기- 쓰기 기능
3-1) glitch 상 create.py를 만든다.
file에 create.py 파일 생성 후 아래의 코드 입력

import sqlite3
conn = sqlite3.connect('db.sqlite3')
curor = conn.cursor()
title = input('title? ')
body = input('body? ')
curor.execute('INSERT INTO topics (title, body) VALUES(?, ?)', (title, body))
conn.commit()
conn.close()

3-2) 이후 table에

python3 create.py

라고 입력하면
title? 라고 나오면 mysql 이후,
body? 라고 나오면 mysql is...
아무말 없으면 error 없이 잘 된것이다.

<참고>
한번 더 확인하기 위해서는 table 상

python3 create.py

입력 후, 아래와 같이 화면이 나오면 잘 된것이다.

4) create에서 read 읽는 법
import는 모듈을 로딩하는 코드로서 마지막에 import read라고 적어야한다.

create.py에서 아래의 코드를 입력한다.


import sqlite3
conn = sqlite3.connect('db.sqlite3')
curor = conn.cursor()
title = input('title? ')
body = input('body? ')
curor.execute('INSERT INTO topics (title, body) VALUES(?, ?)', (title, body))
conn.commit()
conn.close()

import read

이후 terminal에 가서 python3 read.py
title? 이 나오면 oracle
body?라고 나오면 oracle is...라고 치면
1 SQLite
2 mysql
3 oracle

라고 나오면 create에서 read 창 읽어진것이다.

5) server.py에서 topics를 DB로 바꾸는 방법

기존의 topics를 DB로 바꾸면 파일로 저장되므로 정보를 영구적으로 저장할 수 있다.

topics = [
  {"id":1, "title":"html", "body":"html is ...."},
  {"id":2, "title":"css", "body":"css is ...."},
  {"id":3, "title":"js", "body":"js is ...."}
]

5-1) 먼저 sqlite를 사용해야하므로 import sqlite3

from flask import Flask, request, redirect
import sqlite3

5-2) sqlite3에서 connect를 하는 방법

app = Flask(__name__)
import sqlite3

topics = [
  {"id":1, "title":"html", "body":"html is ...."},
  {"id":2, "title":"css", "body":"css is ...."},
  {"id":3, "title":"js", "body":"js is ...."}
]
nextId = 4

def template(content, id=None):
  liTags = ''
  for topic in topics:
    liTags = liTags + f'<li><a href="/read/{topic["id"]}/">{topic["title"]}</a></li>'
  return f'''

에서 for topic in topics:
liTags = liTags + f'

  • <a href="/read/{topic["id"]}/">{topic["title"]}
  • ' 는 글 목록을 만드는 코드

    sqlite3에서 연동시켜서 글목록을 만들도록 함.

    from flask import Flask, request, redirect
    import sqlite3
    
    app = Flask(__name__)
    
    topics = [
      {"id":1, "title":"html", "body":"html is ...."},
      {"id":2, "title":"css", "body":"css is ...."},
      {"id":3, "title":"js", "body":"js is ...."}
    ]
    nextId = 4
    
    def template(content, id=None):
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('SELECT * FROM topics')
      topics = cs.fetchall()
      conn.close()
      liTags = ''
      for topic in topics:
        liTags = liTags + f'<li><a href="/read/{topic[0]}/">{topic[1]}</a></li>'
      return f'''

    로 conn은 connect라는 의미로 db.sqlite3를 connect함.
    이후, 커서(cursor)를 만든다.
    cs = conn.cursor() 를 통하여 cs라는 커서가 생겼다.
    cs.execute('SELECT * FROM topics')를 통하여 커서가 가르키는 결과를 만든다.
    topics = cs.fetchall()를 통하여 db에 있는 정보를 통하여 python화를 시키며 fetch는 '가져온다' 라는 뜻이고 all 은 '모두'라는 의미.
    이것을 topics라는 이름으로 한다.

    5-3) db를 적용한 전체코드

    • SQlite/mysql/oracle 이라고 뜨는 것을 알 수 있다.
    from flask import Flask, request, redirect
    import sqlite3
    
    app = Flask(__name__)
    
    topics = [
      {"id":1, "title":"html", "body":"html is ...."},
      {"id":2, "title":"css", "body":"css is ...."},
      {"id":3, "title":"js", "body":"js is ...."}
    ]
    nextId = 4
    
    def template(content, id=None):
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('SELECT * FROM topics')
      topics = cs.fetchall()
      conn.close()
      liTags = ''
      for topic in topics:
        liTags = liTags + f'<li><a href="/read/{topic[0]}/">{topic[1]}</a></li>'
      return f'''
      <html>
        <body>
          <h1><a href="/">WEB</a></h1>
          <ol>
            {liTags}
          </ol>
          {content}
          <ul>
            <li><a href="/create/">create</a></li>
            <li>
              <form action="/delete/{id}/" method="POST">
                <input type="submit" value="delete">
              </form>
            </li>
          </ul>
        </body>
      </html>
      '''
    
    @app.route("/")
    def index():
      return template('<h2>Welcome</h2>Hello, WEB!')
    
    @app.route("/read/<int:id>/")
    def read(id):
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('SELECT * FROM topics WHERE id=?', (id,))
      conn.close()
      title = ''
      body = ''  
      for topic in topics :
        if topic['id'] == id:
          title = topic['title']
          body = topic['body']
          break;
      return template(f'<h2>{title}</h2>{body}', id)
    
    @app.route('/create/')
    def create():
      content = '''
        <form action="/create_process/" method="POST">
          <p><input type="text" name="title" placeholder="title"></p>
          <p><textarea name="body" placeholder="body"></textarea></p>
          <p><input type="submit" value="create"></p>
        </form>
      '''
      return template(content)
    
    @app.route('/create_process/', methods=['POST'])
    def create_process():
      global nextId
      title = request.form['title']
      body = request.form['body']
      newTopic = {"id":nextId, "title": title, "body": body}
      topics.append(newTopic)
      nextId = nextId + 1
      return redirect(f'/read/{nextId-1}/')
    
    
    @app.route('/delete/<int:id>/', methods=['POST'])
    def delete(id):
      for topic in topics:
        if topic['id'] == id:
          topics.remove(topic)
          break;
      return redirect('/')
     
    # # @app.route('/update/')
    # # def update():
    # #   return 'Update'
     
    
    app.run()
    
    

    <참고>

    fatchone: 한 건만 가져오고 싶은 경우 사용
    fatchall: list 안에 나타남

    6) 2022. 04. 01 bootstrap+css 등 합쳤을때 최종

    from flask import Flask, request, redirect
    import sqlite3
    
    app = Flask(__name__)
    
    topics = [
      {"id":1, "title":"html", "body":"html is ...."},
      {"id":2, "title":"css", "body":"css is ...."},
      {"id":3, "title":"js", "body":"js is ...."}
    ]
    
    
    def template(content, id=None):
      contextUI = ''
      if id != None:
        contextUI = '<input type="submit" value="delete" class="btn btn-dark">'
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('SELECT * FROM topics')
      topics = cs.fetchall()
      conn.close()
      liTags = ''
      for topic in topics:
        liTags = liTags + f'<li><a href="/read/{topic[0]}/">{topic[1]}</a></li>'
      return f'''
      <html>
        <head>
          <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
          <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
          <style>
            h1{{
              border-bottom:10px solid pink;
            }}
            h1>a{{
              text-decoration:none;
            }}
          </style>
        </head>
        <body class="container">
          <input type="button" value="night" onclick="
            document.querySelector('body').style.backgroundColor = 'black';
            document.querySelector('body').style.color = 'white';
          ">
          <h1><a href="/">WEB</a></h1>
          <ol>
            {liTags}
          </ol>
          {content}
          <form action="/delete/{id}/" method="POST">
            <div class="btn-group" role="group" aria-label="Basic example">  
              <a href="/create/" class="btn btn-dark">create</a>
              {contextUI}
            </div>
          </form>
          
        </body>
      </html>
      '''
    
    @app.route("/")
    def index():
      return template('<h2>Welcome</h2>Hello, WEB!')
    
    @app.route("/read/<int:id>/")
    def read(id):
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('SELECT * FROM topics WHERE id=?', (id,))
      topic = cs.fetchone()
      conn.close()
      title = topic[1]
      body = topic[2]
      return template(f'<h2>{title}</h2>{body}', id)
    
    @app.route('/create/')
    def create():
      content = '''
        <form action="/create_process/" method="POST">
          <p><input type="text" name="title" placeholder="title"></p>
          <p><textarea name="body" placeholder="body"></textarea></p>
          <p><input type="submit" value="create"></p>
        </form>
      '''
      return template(content)
    
    @app.route('/create_process/', methods=['POST'])
    def create_process():
      title = request.form['title']
      body = request.form['body']
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('INSERT INTO topics (title, body) VALUES(?,?)',(title,body))
      id = cs.lastrowid
      conn.commit()
      conn.close()
      return redirect(f'/read/{id}/')
    
    
    @app.route('/delete/<int:id>/', methods=['POST'])
    def delete(id):
      
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('DELETE FROM topics WHERE id = ?',(id,))
      conn.commit()
      conn.close()
      
      return redirect('/')
     
    # # @app.route('/update/')
    # # def update():
    # #   return 'Update'
     
    
    app.run()

    결과-1) home 화면

    결과-2) sqlite 눌렀을때의 화면

    • delete 창이 나타나는 것을 알 수 있음

    결과-3) night를 눌렀을 때

    1. 학습한 내용 중 어려웠던 점 또는 해결못한 것들
      3교시 수업시간 내용인 스스로 create 를 구현하는 방법이 어려웠다.
    @app.route('/create/')
    def create():
      content = '''
        <form action="/create_process/" method="POST">
          <p><input type="text" name="title" placeholder="title"></p>
          <p><textarea name="body" placeholder="body"></textarea></p>
          <p><input type="submit" value="create"></p>
        </form>
      '''
      return template(content)
    
    @app.route('/create_process/', methods=['POST'])
    def create_process():
      global nextId
      title = request.form['title']
      body = request.form['body']
      newTopic = {"id":nextId, "title": title, "body": body}
      topics.append(newTopic)
      nextId = nextId + 1
      return f'success!! go:/read/{nextId-1}/'
    1. 해결방법 작성
      수업동영상 참고
    @app.route('/create_process/', methods=['POST'])
    def create_process():
      global nextId
      title = request.form['title']
      body = request.form['body']
      newTopic = {"id":nextId, "title": title, "body": body}
      topics.append(newTopic)
      nextId = nextId + 1
      return f'success!! go:/read/{nextId-1}/'

    에서

    @app.route('/create_process/', methods=['POST'])
    def create_process():
      title = request.form['title']
      body = request.form['body']
      conn = sqlite3.connect('db.sqlite3')
      cs = conn.cursor()
      cs.execute('INSERT INTO topics (title, body) VALUES(?,?)',(title,body))
      id = cs.lastrowid
      conn.commit()
      conn.close()
      return redirect(f'/read/{id}/')

    로 코드를 완성하였다.

    1. 학습소감
      월말평가도 있었는데 python에서 배열이 0으로 시작하는 부분을 놓쳐서 틀렸고, 오늘 수업 들었던 마지막 플라스크 앱에 데이터베이스 연동부분도 다시 한번 수업을 들어야 그래도 본인이 타인에게 설명할 수 있을정도로 이해 하지 않을까. 라는 생각이 들었습니다.

    좋은 웹페이지 즐겨찾기