callback หรือ call-after คือเทคนิคการใช้ decorator [1] ในภาษา Python มักใช้ร่วมกับ Input และ Output และ Dash Core Compoments เพื่อสร้างระบบที่มีปฏิสัมพันธ์กับผู้ใช้ เช่น
import dash
import dash_core_components as dcc
import dash_html_components as html
ext_css = ['https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.1.2/tailwind.min.css']
app = dash.Dash(__name__, external_stylesheets=ext_css)
app.layout = html.Div(className="md:container md:mx-auto rounded-md shadow p-6 rounded-lg bg-gray-500 px-10",
children=[
html.H1(children='เลือกจังหวัดที่ต้องการ :'),
html.Br(),
dcc.Dropdown(id="province_list",
options=[{'label':clr,'value':clr} for clr in ['---','กรุงเทพฯ','เชียงใหม่','ขอนแก่น','ประจวบคิรีขันธ์']]),
html.Hr(),
html.Div(id='result'),
])
if __name__ == '__main__':
app.run_server('0.0.0.0',debug=True)
ผลที่ได้ตามรูปที่ 1 คือหน้าจอมี interactive component คือ dropdown ปรากฏให้เห็น แต่ยังไม่มีการทำงานด้านข้อมูล
กำหนด Input และ Output
ทั้งสองเป็น class ใน dash.dependencies package นำเข้าสู่ระบบด้วยคำสั่ง
from dash.dependencies import Input,Output
argument ที่ต้องส่งให้กับ Input และ Ouput มีสองอย่างคือ
ตามที่กล่าวมาก่อนหน้าว่า callback อาศัยการทำ decoration ทั้ง Input และ Output ที่ประกาศแล้วจะถูกนำไปเป็น arguments สำหรับ decorator function ชื่อ "callback" ซึ่งเป็น function หนึ่งใน class app (หากยังไม่เข้าใจเรื่อง decoration กรุณาทบทวนเรื่องนี้ใน decorator)
ขั้นตอนต่อไปคือการสร้าง stand alone function เพื่อกำหนดขั้นตอนการประมวลผลข้อมูลที่ได้ ผลลัพธ์ที่ส่งออกไปจาก stand alone function จะถูกส่งต่อให้ component ที่ถูกกำหนดให้เป็น output รับค่าไปแสดง
- id ของ HTML component ที่จะเป็นผู้ส่งข้อมูลและผู้รับข้อมูล
- property ของ HTML component ที่เป็นที่แหล่งเก็บข้อมูลในกรณีของ Input หรือที่ต้องการปรับแต่งในกรณีของ Output
Input(component_id="province_list",component_property="value")
Output(component_id="result",component_property="children")
ตามที่กล่าวมาก่อนหน้าว่า callback อาศัยการทำ decoration ทั้ง Input และ Output ที่ประกาศแล้วจะถูกนำไปเป็น arguments สำหรับ decorator function ชื่อ "callback" ซึ่งเป็น function หนึ่งใน class app (หากยังไม่เข้าใจเรื่อง decoration กรุณาทบทวนเรื่องนี้ใน decorator)
@app.callback(Output(component_id="result",
component_property="children"),
Input(component_id="province_list",
component_property="value")
)
ขั้นตอนต่อไปคือการสร้าง stand alone function เพื่อกำหนดขั้นตอนการประมวลผลข้อมูลที่ได้ ผลลัพธ์ที่ส่งออกไปจาก stand alone function จะถูกส่งต่อให้ component ที่ถูกกำหนดให้เป็น output รับค่าไปแสดง
def display_provice(province):
msg=""
if province=="---" or province is None :
return "You chose nothing."
else:
return ""You chose {}".format(province)
นำ code ทั้งหมดมารวมกัน
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output,Input
ext_css = ['https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.1.2/tailwind.min.css']
app = dash.Dash(__name__, external_stylesheets=ext_css)
app.layout = html.Div(className="md:container md:mx-auto rounded-md \
shadow p-6 rounded-lg bg-gray-500 px-10",
children=[
html.H1(children='เลือกจังหวัดที่ต้องการ :'),
html.Br(),
dcc.Dropdown(id="province_list",
options=[{'label':clr,'value':clr} for clr in ['---','กรุงเทพฯ','เชียงใหม่','ขอนแก่น','ประจวบคิรีขันธ์']]),
html.Br(),
html.Div(id='result'),
])
@app.callback(Output(component_id="result",component_property="children"),
Input(component_id="province_list",component_property="value")
)
def display_provice(province):
msg=""
if province=="---" or province is None :
return "You chose nothing."
else:
return "You chose {}".format(province)
if __name__ == '__main__':
ตัวอย่างที่สองเป็นการทำ callback เพื่อทำการ update การแสดงผลในรูปของกราฟ (ดูเรื่อง bargraph ของ plotly express ประกอบ)
import numpy as np
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output,Input
import plotly.express as px
# -- dataframe
df = pd.read_csv('./data/demo2.csv')
ext_css = ['https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.1.2/tailwind.min.css']
app = dash.Dash(__name__, external_stylesheets=ext_css)
app.layout = html.Div(className="md:container md:mx-auto rounded-md \
shadow p-6 rounded-lg bg-gray-500 px-10",
children=[
html.H1(children='เลือกทวีปที่ต้องการ :'),
html.Br(),
dcc.Dropdown(id="continent_list",
options=[{'label':clr,'value':clr} for clr in ['Asia','Africa','Europe','North America','Oceania','South America']]),
html.Br(),
dcc.Graph(id='bar-graph')
])
@app.callback(Output(component_id="bar-graph",component_property="figure"),
Input(component_id="continent_list",component_property="value")
)
def update_graph(continent):
filtered = df.loc[df['continent']==continent,
['total_cases','total_deaths',
'population','aged_65_older',
'female_smokers','male_smokers']].melt()
filtered['value'] = np.log10(filtered['value'] )
figure = px.bar(filtered,x='variable',y='value',color="value",text="value")
figure.update_layout(transition_duration=500)
return figure
if __name__ == '__main__':
app.run_server('0.0.0.0',debug=True)
สรุปขั้นตอนการทำงาน สำหรับตอนนี้
- สร้าง Output, Input instance และกำหนด component id, component property เพื่อให้ระบบทราบว่าจะไปเอาข้อมูลจากที่ไหน ไปแสดงที่ไหน
- ส่ง Output และ Input เป็น argument ให้กับ callback function
- สร้าง stand alone function ขึ้นมาเพื่อกำหนดขั้นตอนการประมวลผลข้อมูล
Sign up here with your email
ConversionConversion EmoticonEmoticon