동적 데이터베이스 업데이트 및 복원
Action1. Modal 팝업창에서 '수정하기' 버튼을 클릭해 DB를 업데이트했다면, AG Grid의 데이터베이스를 다시 조회
Action2. Modal 팝업창에서 '닫기' 버튼을 클릭했을 때, 팝업창에서 내용을 수정했어도 기존의 상태로 복원
사용자가 모달에서 "수정하기" 버튼을 클릭했을 때 ag_grid_1의 데이터베이스를 업데이트하려면, toggle_modal_edit 콜백에서 데이터베이스 수정 로직을 완료한 후, ag_grid_1의 rowData를 새로 고칠 수 있도록 적절한 출력(Output)을 설정해야 합니다.
toggle_modal_edit 콜백에서 데이터베이스 수정이 완료되었음을 나타내는 신호를 dcc.store를 통해 전달하여 update_grid 콜백의 입력(Input)으로 사용되어, ag_grid_1의 데이터를 새로고침했습니다.
dcc.Store(id='modal-data-store', storage_type='memory'), # 닫기 버튼 클릭시 복원을 위한 data store
dcc.Store(id='modal_edit_update_store'), # 수정하기 버튼 클릭 시 ag_grid 업데이트를 위한 data store
가장 먼저 Layout에 두 개의 dcc.store를 생성해줬습니다. 레이아웃의 위치는 어디에 두셔도 상관없습니다.
이제 각 컴포넌트를 사용해 두 가지 기능을 구현하겠습니다.
@app.callback(
[Output('modal_edit', 'is_open'), Output('modal_edit_update_store', 'data')],
[Input("modal_edit_open", "n_clicks"), Input("edit_close",
"n_clicks"), Input("edit_standard_set", "n_clicks")],
[State('modal_edit', 'is_open'), State('modal_edit_intent_id', 'value'), State('modal_edit_brand_id', 'value'),
State('modal_edit_intent_group', 'value'), State('modal_edit_question',
'value'), State('modal_edit_answer_type', 'value'),
State('modal_edit_call_type', 'value'), State('modal_edit_button_label',
'value'), State('modal_edit_url_call', 'value'),
State('modal_edit_intent_desc', 'value'), State('modal_edit_use_yn', 'value'), State('modal_edit_answer', 'value')]
)
def toggle_modal_edit(n1, n2, n3, is_open, edit_intent_id, edit_brand_id, edit_intent_group, edit_question,
edit_answer_type, edit_call_type, edit_button_label, edit_url_call,
edit_intent_desc, edit_use_yn, edit_answer):
if n1 or n2 or n3: # 순서대로 '표준셋수정하기(open)' 'Close', '수정하기'
if n3: # '수정하기' 버튼 클릭 시
if not edit_question.strip() or not edit_answer.strip():
raise PreventUpdate("질문과 답변 모두 입력해야 합니다.")
# 데이터베이스 연결
engine = create_engine(get_db_info())
with engine.connect() as connection:
# 데이터베이스에 추가하는 쿼리 실행
query = text(f"""
UPDATE db.dard_set
SET brand_id = '{edit_brand_id}',
intent_group = '{edit_intent_group}',
question = '{edit_question}',
answer_type = '{edit_answer_type}',
call_type = '{edit_call_type}',
button_label = '{edit_button_label}',
url_call = '{edit_url_call}',
intent_desc = '{edit_intent_desc}',
use_yn = '{edit_use_yn}',
answer = '{edit_answer}'
WHERE intent_id = '{edit_intent_id}'
""")
result = connection.execute(query)
connection.commit()
return not is_open, {'updated' : True} # 수정하기 버튼을 클릭하여 업데이트를 진행했을 때, updated를 True로 반환.
return not is_open, dash.no_update
return is_open, dash.no_update
콜백 데코레이터에서 Output에 dcc.store의 id인 modal_data_update_store와 속성 값을 data로 지정하겠습니다.
이를 통해 Input 요소에 해당하는 모달에 접근하는 버튼인 modal_edit_open = n1, 모달 내의 닫기 버튼인 edit_close = n2
모달내의 수정하기 버튼인 edit_standard_set = n3 이라는 3가지 입력 요소의 속성값이 변화할 때마다 dcc.store(id= modal_data_update_store)의 파라미터인 'updated'의 값을 다르게 반환합니다.
- 수정하기 버튼(n3) 클릭(is_open)시 updated : True를 반환해 dcc.store에 업데이트를 진행합니다.
- 모달 접근하기 버튼 (n1), 모달 닫기 버튼(n2) 클릭 (is_open) 시 update를 진행하지 않고 dcc.store(id = modal-data-store)에 저장된 데이터로 복원합니다.
@app.callback(
Output('ag_grid_1','rowData'),
[Input('input_1','value'),Input('dropdown_1','value'),
Input('input_2','value'),Input('dropdown_2','value'),
Input('radio-ANDOR','value'),Input('checkbox-EM','value'),Input('checkbox-TR','value'),Input('checkbox-NB','value'),Input('checkbox-ZZ','value'),Input('checkbox-DD','value'),Input('modal_edit_update_store', 'data')]
)
def update_grid(input_value, dropdown_value, input_value2, dropdown_value2, radio_andor_value, checkbox1_value, checkbox2_value, checkbox3_value, checkbox4_value, checkbox5_value, update_store_data):
if input_value is None:
input_value = ''
else:
input_value = input_value.upper()
if input_value2 is None:
input_value2 = ''
else:
input_value2 = input_value2.upper()
check_values=[]
if checkbox1_value :
check_values.append('A')
if checkbox2_value :
check_values.append('B')
if checkbox3_value :
check_values.append('C')
if checkbox4_value :
check_values.append('D')
if checkbox5_value :
check_values.append('E')
# check_values가 비어 있으면 더미 값 '-1'을 사용
if not check_values:
check_values.append('-1')
checkbox_values = ', '.join(f"'{item}'" for item in check_values)
operator = radio_andor_value
engine = create_engine(db_info)
with engine.connect() as connection:
query = text(
f"SELECT intent_id, brand_id, intent_group, question, answer, use_yn, uid FROM bdb.set WHERE {dropdown_value} LIKE :x {operator} {dropdown_value2} LIKE :y AND brand_id IN ({checkbox_values}) ORDER BY uid ASC")
result = connection.execute(
query, {"x": '%' + input_value + '%', "y": '%' + input_value2 + '%'}).fetchall()
# Convert the SQL result to the ag-Grid compatible format
grid_data= [{"intent_id": row[0], "brand_id": row[1], "intent_group": row[2], "question": row[3], "answer": row[4], "use_yn": row[5]} for row in result]
if update_store_data and update_store_data.get('updated'): # toggle_modal_edit에서 수정하기 버튼을 클릭했을 시 , updated가 True가 되면서 해당 코드를 실행해 ag_grid를 한번 더 업데이트 진행.
return grid_data
return grid_data
다음으로 앞서 레이아웃에 구성한 dcc.store의 id를 콜백 데코레이터의 Input에 추가해줍니다.
속성값은 data를 저장할 것이기 때문에 data로 지정해줬습니다.
if update_store_data and update_store_data.get('updated'): # toggle_modal_edit에서 수정하기 버튼을 클릭했을 시 , updated가 True가 되면서 해당 코드를 실행해 ag_grid를 한번 더 업데이트 진행.
return grid_data
Ag_grid를 업데이트 하는 update_grid 함수에 위의 코드를 추가하여, dcc.store(update_store_data)의 updated가 True일 경우 다시 Ag_grid를 업데이트 하는 로직을 추가합니다.
이는 앞서 모달의 업데이트를 관리하는 toggle_modal_edit 함수에서 모달의 수정하기 버튼(n3)이 클릭 됐을 시 dcc.store의 'updated'를 True로 반환하게 될 때, Ag_grid를 다시 한번 업데이트 합니다.
if triggered_id == 'edit_close': # '닫기' 버튼 클릭 시 dcc.store에 저장해둔 데이터 복원.
if stored_data:
return stored_data.get('intent_id', ''), stored_data.get('brand_id', ''), stored_data.get('intent_group', ''), stored_data.get('question', ''), stored_data.get('answer_type', ''),stored_data.get('call_type', ''),stored_data.get('button_label', ''),stored_data.get('url_call', ''),stored_data.get('intent_desc', ''),stored_data.get('use_yn', ''),stored_data.get('answer', ''),stored_data
return '', '', '', '', '', '', '', '', '', '', '',{}
반대로 모달의 닫기 버튼 클릭 시 dcc.store(id = modal-data-store)에 저장된 데이터로 ag_grid를 복원합니다.
결론
이를 통해 데이터베이스를 실시간으로 업데이트하고, 웹에서 실시간으로 반응하는 기능을 구현했습니다.
'개발 > Dash' 카테고리의 다른 글
[Dash]Python Dash Callback (3) 팝업창에 경고 메시지 띄우기 + 콜백 합치기 (0) | 2024.01.17 |
---|---|
[Dash]Python Dash Callback (2) State (0) | 2024.01.16 |
[Dash]Python Dash Callback (1) 콜백 트리거 속성 (0) | 2024.01.16 |
[Dash]Python Dash Layout 구성 (3) feat. Dash AG Grid (0) | 2024.01.15 |
[Dash]Python Dash Layout 구성 (2) feat. dash_core_components (0) | 2024.01.15 |