on
flask에서 sql을 사용하는 방식
flask에서 sql을 사용하는 방식
flask에서 sql을 사용하는 방식
크게 두가지 정도 있는듯.
query_engine에 포함시켜 쿼리를 날리고 결과를 받는 방식 정의된 model 자체를 받아 사용하는 방식
query_engine 방식
#query_engine.py def TaskQuery(): sql = "SELECT * FROM task_list" lresult = db.engine.execute(sql) return lresult ~~~ #task_view.py result = query_engine.TaskQuery() ~~~ return render_template('/task/taskOverView.html',data=result)
query_engine에 사용할 쿼리문을 정의하여 sql 쿼리 실행 결과를 받아와 사용하는 방식.
이때 반환되는 데이터의 타입은 'sqlalchemy.engine.cursor.LegacyCursorResult'
랜더할때 데이터를 그대로 인자로 전달해주면 템플릿에서는 딕셔너리나 리스트를 사용하듯이 데이터를 출력해서 사용할 수 있다.
{% for value in data %} 완료 처리 작업 배정 배정 취소 {{ value[1] }} {{ value[2] }} {{ value[3][:-7]}} {{ value[4] }} {{ value[5] }} {{ value[7] }} {% endfor %}
{% for value in data %} {{ value['KST'] }} {{ value['TypeName'] }} {{ value['AccountKey'] }} {{ value['NickName'] }} {% endfor %}
이경우 데이터를 쓰는 방식은 dict나 리스트 등의 일반적인 자료 형태와 동일하지만, 엄밀하게 따지면 다르기 때문에 .append 등을 통한 데이터의 추가나 삭제등이 힘들다.
for s in result : print(type(s)) print(s) 'sqlalchemy.engine.row.LegacyRow' (1, '', '', '2021-09-08 12:57:53.914909', '', '미배정', 'Unsigned', 'd41d8cd98f00b204e9800998ecf8427e') (2, '', '', '2021-09-08 12:59:21.561642', '', '미배정', 'Unsigned', '74399a7fe9df8c6c930b775d66b97759')
데이터 자체를 그대로 사용하기엔 용이하지만, 가공이나 변형을 거쳐 쓰기엔 여러모로 불편한 타입. 쿼리문에서 출력할 데이터 형태를 미리 완성해두고 결과물을 가져와서 출력만 하겠다는 생각으로 쓰기에 적절해보인다.
list방식과 dict 방식 둘 다 사용 가능한 기묘한 형태.
model.query 방식
#models.py class TaskList(db.Model): id = db.Column(db.Integer, primary_key=True) binname = db.Column(db.String(100),nullable=False) comment = db.Column(db.String(100),nullable=False) date = db.Column(db.DateTime(),nullable=False) reqname = db.Column(db.String(100),nullable=False) mgrname = db.Column(db.String(100),nullable=False) status = db.Column(db.String(100),nullable=False) hash = db.Column(db.String(100)) ~~ #task_view.py res1 = TaskList.query.filter(TaskList.mgrname==i.user_id) dict_result1 = pd.read_sql(res1.statement, res1.session.bind)
정의된 DB 테이블 model을 가져와 필요한 데이터만 필터링하여 pandas의 read_sql() 함수를 가지고 변환해 쓰는 방식. 이 경우는 변환되는 데이터 타입이 pandas.core.frame.DataFrame 이된다.
dataframe 형태로 변환되기 때문에 판다스에서 사용하는 각종 데이터 라이브러리를 사용하기에 용이하다. (다만 지금은 그정도로 큰 데이터셋을 사용하지 않아 체감은 못해봄. )
print(dict_result.loc[0]) ~~~ id 1 originid 6 binname README.txt comment 오진 date 2021-09-08 14:16:03 enddate 2021-09-09 12:06:06.022682 reqname mgrname synod2 reportpath C:\Users\synod2\Documents\GitHub\WT_Optool_mai... endstatus 정상 파일 hash 72ac5a8dd6491e525b9783c9bc439fe6
이런식으로 데이터를 보거나 관리하기에는 용이한데, 간편하게 출력해서 보기엔 적합하지 않다. 판다스 데이터프레임 형태이기 때문에 query_engine처럼 템플릿에서 출력하려면 to_html을 쓰거나 딕셔너리나 리스트로의 별도의 변환이 필요하다.
for s in (dict_result.values.tolist()): print (s) ~~ [1, 6, 'README.txt', '오진', '2021-09-08 14:16:03', Timestamp('2021-09-09 12:06:06.022682'), '', 'synod2', 'C:\\Users\\synod2\\Documents\\GitHub\\WT_Optool_main\\WonderOps\\static\\TaskReports\\sample2jfif.jfif_2021-09-09_120606.022682', '정상 파일', '72ac5a8dd6491e525b9783c9bc439fe6'] [2, 5, 'Everytime 십일절 - 11번가.url', '', '2021-09-08 13:07:58', Timestamp('2021-09-09 12:06:37.401863'), 'aaaa', 'synod2', 'C:\\Users\\synod2\\Documents\\GitHub\\WT_Optool_main\\WonderOps\\static\\TaskReports\\12.txt_2021-09-09_120637.401863', '기타', 'ec43f54b31e22fc56846ae8a1c6dcb78']
tolist() 메소드를 쓰면 list 형태로 바꿔준다. 이 경우는 각 요소를 문자열 형태가 아닌 오브젝트 자체를 반환하는 방식이기 때문에 indices 등을 이용한 정규표현식 사용이 힘들 수 있다.
예를들면, 위 예시의 경우 Timestamp 가 문자열이 아니고 오브젝트 형태로 반환되기 때문에 별도의 변환을 거치지 않으면 문자열 정규표현식 사용이 불가하다.
#task_view.py ~~ qs = TaskList.query.filter(TaskList.mgrname==g.user.user_id) res = pd.read_sql(qs.statement, qs.session.bind) result = res.values.tolist() return render_template('/task/taskOverView.html',data=result) ~~ {{ value[1] }} {{ value[2] }} {{ ((value[3])|string)[:-7] }}
만약 위 Timestamp 오브젝트를 템플릿에서 문자열처럼 쓰고싶으면 위와 같이 |string 지시자를 붙여 문자열 형태로 변환해주면 된다. (jinja에서 사용하는 자료형 변환식)
to_dict 메소드를 쓰면 딕셔너리 형태로 바꿔주지만, 이경우는 dict 처럼 쓰지는 못한다.
qs = TaskList.query.filter() res = pd.read_sql(qs.statement, qs.session.bind) result = res.values.tolist() for i,s in enumerate(result) : result[i].append('1')
이렇게 쓰면 append 등을 통해 원하는 데이터를 자유롭게 붙일 수 있다.
번외. pandas dataframe 에서 특정 데이터 값만 뽑아오기
qs = TaskList.query res = pd.read_sql(qs.statement, qs.session.bind) result = res.values.tolist() cs = CompleteTaskList.query cres = pd.read_sql(cs.statement, cs.session.bind) for i,s in enumerate(result) : if (s[6]) == "Complete" : tmp = cres[cres['originid'] == s[0]] result[i].append(tmp['enddate'].values[0])
tasklist에서 6번째 값이 complete인 행을 찾고, 해당 행의 0번째 값인 id와 동일 id값을 가지는 행을 completeTaskList에서 찾은 다음, 그 행의 특정 속성값을 가져와 기존 리스트에 추가하는 기능.
from http://my-repo.tistory.com/93 by ccl(A) rewrite - 2021-10-02 21:26:46