SQL 처리 페이지

매일 공부(ML)·2021년 11월 19일
0

CS 

목록 보기
28/33

SQL 처리 페이지

  • 순서

    	- DB 이름 입력
    • SQL문 입력
    • SELECT문이 들어간 SQL문이면 결과화면 보여주도록 넘기기

  • HTML CODE
$ 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>
  • PYTHON CODE
$ 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
  • 앱 실행 후 INDEX 페이지 접속

코드 분석

  1. 함수
  • 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
  1. 데이터베이스 이름

  • 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
  1. SQL입력
  • HTML CODE

    • textarea를 만듭니다. 플라스크에서 인식할 수 있는 이름은 sql입니다. cols는 한 줄에 최대 40개가 가능하며, 10줄이 넘어가면 스크롤이 생긴답니다.
<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
profile
성장을 도울 아카이빙 블로그

0개의 댓글