Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Best practices for sequential data from a dcc.Upload ? (Sessions?) - UPDATED WITH SOLUTION

UPDATE WITH SOLUTION

In case this could help anyone in the future:

I have created a dictionary where I will store the session_ids as key and the data as the value.
(In production, this dictionary will need to be concurrent).

Then, to the function that is triggered when an file is dropped or uploaded:

global mySession
    
    # If user don't have a session, create it
    if session_id not in mySession:
        mySession[session_id] = {}

    ## CASE MULTIPLE FILES ARE DROPPED TOGETHER
    # For each file dropped 
    if list_of_files is not None:

        data = [parse_files(c, n) for c, n in zip(list_of_files, list_of_filenames)]
        
        ## CASE NEW FILES ARE DROPPED SEQUENTIALLY
        # First assure we have data if not create empty list
        if 'data' not in  mySession[session_id].keys():
            mySession[session_id]['data'] = list()

        # If we indeed already had data uploaded in this session
        mySession[session_id]['data'] += data

com-video-to-gif

ORIGINAL POST

Hi,

I already have the functionality for a user to drop/upload a file and plot it.

I would like to extend this functionality. If the user now drops another file, I would like the plot to add a new line, instead of overwriting the current plot. (The same problem happens also if user drops 3 files at the same time).

Would it be interesting to use a session object to define a logic: if I have previous data gather it, if not just plot this data? Or how should I better do it?

This is the current implementation:

def parse_files(contents, filename, session_id):
    '''
    Recieve a encoded file, transforme it and return the graph.
    '''
    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)
    
   # Data manipulation
   ## HERE I COULD ASK TO THE SESSION OBJECT FOR INFORMATION?
    
    return html.Div([
        dcc.Graph(
            id='example-graph',
            figure={
                'data': transformed,
                'layout': {
                    'title': filename
                }
            }
        )
    ])
    
# React to a file being dropped    
@app.callback(Output('output_data_upload', 'children'), 
              [Input('upload_data', 'contents')], 
              [State('upload_data', 'filename')])
def update_output(list_of_contents, session_id, list_of_filenames):
    '''
    Pass each file to the parser and return the information into the graph div
    Current problems:
    =================
        It is stacking the different graphs that recieves instead of a list on children attr
    '''
    # For each file dropped
    if list_of_contents is not None:
        children = [
            parse_files(c, n, session_id) for c, n in zip(list_of_contents,list_of_filenames)]
        return children

Thank you very much,
Pablo