순서
- DB 이름 입력
$ vi ~/aiffel/flask_app/pyproject/templates/data.html
<html>
<head>
<title>SQL 처리 페이지</title>
</head>
<body>
<h1>SQL 처리 페이지</h1>
<form action="/dbsql" method="POST">
<h2>데이터베이스 이름</h2>
<span> <input type="text" name="db_name" placeholder="ex)name.db"> </span>
<h2>SQL (명령어 한 줄만 가능)</h2>
<textarea name="sql" cols="40" rows="10" placeholder="ex) SELECT * FROM table_name"></textarea>
<br>
{% if label %}
<span class="result_lable">
{% block content %}
{{ label }}
{% endblock %}
</span>
<br>
{% endif %}
<button type="submit">SQL 전송</button>
</form>
</body>
</html>
$ vi ~/aiffel/flask_app/pyproject/app_data.py
from flask import Flask, render_template, request
from flask_ngrok import run_with_ngrok
import os
import sqlite3
import pandas as pd
app = Flask(__name__)
run_with_ngrok(app)
'''
DB 함수
'''
def get_db(db_name):
return sqlite3.connect(db_name)
def sql_command(conn, command):
try :
conn.execute(command)
conn.commit()
command = command.lower()
if "select" in command:
command_split = command.split(" ")
select_command = "SELECT * FROM " + command_split[command_split.index("from")+1]
df = pd.read_sql(select_command, conn, index_col=None)
html = df.to_html()
conn.close()
return html, 1
conn.close()
return True, 1
except Exception as exception:
conn.close()
return False, exception
'''
File upload
'''
@app.route("/index")
def index():
return render_template('data.html')
@app.route('/dbsql', methods=['POST'])
def sql_processing():
if request.method == 'POST':
con = get_db('/' + request.form.get('db_name'))
sql = request.form.get('sql')
result_sql, excep = sql_command(con, sql)
if result_sql == False :
return render_template('data.html', label="비정상" + str(excep))
elif result_sql == True :
return render_template('data.html', label="정상 작동")
else :
result_sql = "<html><body> " + result_sql + "</body></html>"
return result_sql
if __name__ == '__main__':
app.run()
$ python ~/aiffel/flask_app/pyproject/app_data.py
try-except 문으로 try 안의 코드가 정상적으로 작동하면 try만 실행됩니다. 만약 정상적으로 작동 안 하고 에러가 난다면 except 아래의 코드가 실행됩니다.
command = command.lower() :명령어를 소문자로 바꿉니다. command 뒤에 붙은 lower() 함수가 문자열 값을 모두 소문자로 바꿔줍니다.
def get_db(db_name): #DB연결
return sqlite3.connect(db_name)
def sql_command(conn, command): #SQL 이용하여 DB에 명령 내리기
try :
conn.execute(command)
conn.commit()
command = command.lower()
if "select" in command:
command_split = command.split(" ")
select_command = "SELECT * FROM " + command_split[command_split.index("from")+1]
df = pd.read_sql(select_command, conn, index_col=None)
html = df.to_html()
conn.close()
return html
conn.close()
return True
except :
conn.close()
return False
SQL문 안에 "select"가 들어 있으면 아래의 코드를 실행합니다.
SQL문을 " "(빈칸)을 기준으로 나눠서 리스트에 넣습니다. 예를 들어, SELECT FROM table 이면 ['SELECT', '', 'FROM', 'table']로 나뉩니다.
select_command에 "SELECT * FROM "과 command_split[command_split.index("from")+1] 에서 나온 글씨를 합칩니다.
command_split[command_split.index("from")+1] : 위에서 SQL을 빈칸으로 나눈 리스트 from이 위치한 곳의 index 값에 1을 더한 위치에 있는 단어를 가져옵니다.
판다스 모듈에 있는 read_sql 함수를 사용합니다
to_html()을 이용해서 dataframe을 HTML 형식으로 바꿔줍니다. dataframe은 표 형식으로 되어 있습니다.
표 모양의 HTML 코드가 반환됩니다
if "select" in command:
command_split = command.split(" ")
select_command = "SELECT * FROM " + command_split[command_split.index("from")+1]
df = pd.read_sql(select_command, conn, index_col=None)
html = df.to_html()
conn.close()
return html
HTML CODE
action="/dbsql" : app.py에 dbsql이라고 라우팅 된 함수를 실행합니다.
method="POST" : 데이터 전달 방식은 POST를 이용합니다.
<form action="/dbsql" method="POST">
<h2>데이터베이스 이름</h2>
<span> <input type="text" name="db_name" placeholder="ex)name.db"> </span>
PYTHON CODE
'/dbsql' : 바로 위 HTML 코드에서
부분이 있습니다. 여기서 action="/dbsql"을 라우팅하고 있는 파이썬 함수가 여기라는 것을@app.route('/dbsql', methods=["POST"]) 가 말하고 있는 것 입니다.
methods=["POST"] : 데이터 전달 방식은 POST를 이용합니다.
데이터베이스 연결 함수인 get_db를 이용해서 DB의 연결 객체를 con에 넣습니다.
'''
File upload
'''
@app.route("/index")
def index():
return render_template('data.html')
@app.route('/dbsql', methods=['POST'])
def sql_processing():
if request.method == 'POST':
con = get_db(request.form.get('db_name'))
sql = request.form.get('sql')
result_sql = sql_command(con, sql)
if result_sql == False :
return render_template('data.html', label="비정상")
elif result_sql == True :
return render_template('data.html', label="정상 작동")
else :
result_sql = "<html><body> " + result_sql + "</body></html>"
return result_sql
HTML CODE
<h2>SQL (명령어 한 줄만 가능)</h2>
<textarea name="sql" cols="40" rows="10" ></textarea>
<br>
{% if label %}
<span>
{% block content %}
{{ label }}
{% endblock %}
</span>
<br>
{% endif %}
<button type="submit">SQL 전송</button>
PYTHON CODE
DB에 명령을 내리는 함수인 sql_command()에 HTML의 textarea에 입력했던 sql문을 넣기
반환된 것을 result_sql에 넣습니다. sql_command() 함수에서 반환되는 결과물은 True, False 그리고 SELECT문이 들어왔을 때 HTML 코드를 반환.
result_sql=False, 말 그대로 SQL문을 DB에서 돌리던 중에 오류가 생겨서 비정상적으로 종료가 되었다는 의미입니다.
HTML의 기본 태그 앞 뒤로 붙이기
@app.route('/dbsql', methods=['POST'])
def sql_processing():
if request.method == 'POST':
con = get_db(request.form.get('db_name'))
sql = request.form.get('sql')
result_sql = sql_command(con, sql)
if result_sql == False :
return render_template('data.html', label="비정상")
elif result_sql == True :
return render_template('data.html', label="정상 작동")
else :
result_sql = "<html><body> " + result_sql + "</body></html>"
return result_sql