Callbacks with dcc.Store in a loop

Hi,

is it possible to send data to dcc.Store in a loop?

I am trying to do something like:

metric_names = {
    "dbName_01":"metric_01",
    "dbName_02":"metric_02",
}

for m,n in metric_names.items():
    @app.callback(
        output=Output(f'intermediate-{n}', 'data'),
        inputs=Input('url', 'search'))
    def get_value(n):
        data = pd.DataFrame(list(db.collection.find({},{
            "months_12":f"${m}.12Months",
            "months_24":f"${m}.24Months",
            "months_36":f"${m}.36Months",
            "_id":0
        })))
        return json.dumps(data.to_dict(), default=str)

But when I get the data on another page with:

for m in metric_names.values():
    @callback(
        output=Output(f'{m}', 'children'),
        inputs=[
            Input(f'intermediate-{m}', 'data'),
            State(f'intermediate-{m}', 'data'),
            ])
    def get_value(data, _):
        if data is not None:
            data = pd.DataFrame(json.loads(data))
            graph = dcc.Graph(
                figure=get_growth_histogram(data, lower_clip=-100, upper_clip=1_000),
                style={"width": "100%"})
            return graph
        else:
            return no_update

I get the same graph in each iteration…

Getting the graphs in a loop works, when I don’t have the dcc.Store loop. That is why I think it is due to the dcc.Store loop.

Cheers
Nils

As long as the data is different in the stores, then it should be different.

Well, that’s the point.
The problem is just the stupid way I tried to pass the m into my callback function.
To pass the m correctly, I added some html.Data to my Layout:

*[html.Data(id=f"{m}-tmp", key=f"{m}") for m,_ in metric_names.items()],

And I grabbed the key from there to pass it into the callbacks.
Feels very hacky though :smiley:

for m,n in metric_names.items():
    @app.callback(
        output=Output(f'intermediate-{n}', 'data'),
        inputs=Input(f"{m}-tmp", 'key'))
    def get_value(metric):
        data = pd.DataFrame(list(db.collection.find({},{
            "months_12":f"${metric}.12Months",
            "months_24":f"${metric}.24Months",
            "months_36":f"${metric}.36Months",
            "_id":0
        })))
        return json.dumps(data.to_dict(), default=str)

Cheers
Nils

I mean, another less hacky way to go about it would be to use pattern-matching MATCH.

That is interesting, thanks for the advice - I’ll have a look!

Meanwhile I also found a less hacky way, by just passing the dcc.Store id as input to the callback. That way everything is way more readable.

Cheers
Nils

1 Like