2828import json
2929import inspect
3030
31+ import dash
3132from dash import Dash
32- from dash ._utils import split_callback_id
33+ from dash ._utils import split_callback_id , inputs_to_dict
34+
3335from flask import Flask
3436
3537from django .urls import reverse
4446from .util import serve_locally as serve_locally_setting
4547from .util import stateless_app_lookup_hook
4648
49+ try :
50+ from dataclasses import dataclass
51+ from typing import Dict , List
52+
53+ @dataclass (frozen - True )
54+ class CallbackContext :
55+ inputs_list : List
56+ inputs : Dict
57+ states_list : List
58+ states : Dict
59+ outputs_list : List
60+ outputs : Dict
61+ triggered : List
62+
63+ except :
64+ # Not got python 3.7 or dataclasses yet
65+ class CallbackContext :
66+ def __init__ (self , ** kwargs ):
67+ self ._args = kwargs
68+
69+ @property
70+ def inputs_list (self ):
71+ return self ._args ['inputs_list' ]
72+
73+ @property
74+ def inputs (self ):
75+ return self ._args ['inputs' ]
76+
77+ @property
78+ def states_list (self ):
79+ return self ._args ['states_list' ]
80+
81+ @property
82+ def states (self ):
83+ return self ._args ['states' ]
84+
85+ @property
86+ def outputs (self ):
87+ return self ._args ['outputs' ]
88+
89+ @property
90+ def outputs_list (self ):
91+ return self ._args ['outputs_list' ]
92+ @property
93+ def triggered (self ):
94+ return self ._args ['triggered' ]
95+
96+
4797uid_counter = 0
4898
4999usable_apps = {}
@@ -89,6 +139,7 @@ def get_local_stateless_by_name(name):
89139
90140 return sa
91141
142+
92143class Holder :
93144 'Helper class for holding configuration options'
94145 def __init__ (self ):
@@ -100,6 +151,7 @@ def append_script(self, script):
100151 'Add extra script file name to component package'
101152 self .items .append (script )
102153
154+
103155class DjangoDash :
104156 '''
105157 Wrapper class that provides Dash functionality in a form that can be served by Django
@@ -511,8 +563,31 @@ def dispatch(self):
511563 def dispatch_with_args (self , body , argMap ):
512564 'Perform callback dispatching, with enhanced arguments and recording of response'
513565 inputs = body .get ('inputs' , [])
514- state = body .get ('state' , [])
566+ input_values = inputs_to_dict (inputs )
567+ states = body .get ('state' , [])
515568 output = body ['output' ]
569+ outputs_list = body .get ('outputs' ) or split_callback_id (output )
570+ changed_props = body .get ('changedPropIds' , [])
571+ triggered_inputs = [{"prop_id" : x , "value" : input_values .get (x )} for x in changed_props ]
572+
573+ callback_context_info = {
574+ 'inputs_list' : inputs ,
575+ 'inputs' : input_values ,
576+ 'states_list' : states ,
577+ 'states' : inputs_to_dict (states ),
578+ 'outputs_list' : outputs_list ,
579+ 'outputs' : outputs_list ,
580+ 'triggered' : triggered_inputs ,
581+ }
582+
583+ callback_context = CallbackContext (** callback_context_info )
584+
585+ # Overload dash global variable
586+ dash .callback_context = callback_context
587+
588+ # Add context to arg map, if extended callbacks in use
589+ if len (argMap ) > 0 :
590+ argMap ['callback_context' ] = callback_context
516591
517592 outputs = []
518593 try :
0 commit comments