How to make dash app works correctly with requests from an API

Hi!

I am trying to make an app that takes input (player ID), get info about the player from an API using Requests, then do some cleaning with Pandas and finally makes plots. I manage to make it work but it’s simply not what I want and it looks horribly (input, request, data cleaning and plots are in one callback, blehh :/). There where tons of problems, whenever I dealt with one the app gave me another (all works fine in separated script without the dash app). I don’t want anybody to write or fix the code for me, just some tips/clues/guidence or general idea about how it should be done.

Thanks in advance and sorry if the description isn’t clear, I can specify more details but I didn’t want to make this post 28 pages long.

Can you share the exact problem you need help with, some sample code to reproduce the issue(s) and a link/screenshot of what your app output currently looks like? Without some more specific details, it’ll be difficult to provide advice or help with the implementation.

If you could review this part:

@app.callback([Output(“wins_pie”, “figure”),
Output(“side”, “figure”),
Output(“kda_bar”, “figure”),
Output(“stacked_bar”, “figure”),
Output(“top_all_time_wins”, “figure”),
Output(“top_friends”, “figure”),
Output(“top_win_friends”, “figure”)],
[Input(“info_button”, “n_clicks”)],
[State(“insert_id”, “value”)]
)

def update_fig(*args):

if not any(args):
    raise PreventUpdate
else:
    num_clicks, player_id = args

# get player info and make dataframes
if num_clicks > 0:
    r = requests.get(f'https://api.opendota.com/api/players/{player_id}')

if r.ok:
    player_df = pd.DataFrame(json.loads(r.text))

matches_link = f'https://api.opendota.com/api/players/{player_id}/matches?significant=0'
r = requests.get(matches_link)
player_matches_df = pd.DataFrame(json.loads(r.text))

player_heroes_link = f'https://api.opendota.com/api/players/{player_id}/heroes'
r = requests.get(player_heroes_link)
player_heroes_df = pd.DataFrame(json.loads(r.text))

player_peers = f'https://api.opendota.com/api/players/{player_id}/peers'
r = requests.get(player_peers)
player_peers_df = pd.DataFrame(json.loads(r.text))

I think this is the problematic part of the code. The layout is fine and the code after this part is also fine (it’s just cleaning data with Pandas), or at least i think so.

One problem that i had was that I couldn’t do the request part before the app because the script was running in circle (input → app runs → input shows again) so i did the “insert_id” field in the app.

Second was that I tried to add a feature with a dropdown containing a list of most played hero to display some stats but since the info about the heroes comes from request in the callback I couldn’t place it in the layout… Maybe chained callbacks would get the job done?

Another problem was that everytime I wanted to add an argument to this function (for example to make a dropdown with all heroes, not depending on API info) dash would throw errors about everything. First that json is wrong, then the error about scalar values needing index, then about return statement beeing wrong (or None), I’ve manage to fix it all, but then it thrown an error about missing column in axis, as if the data was already cleaned and those column were missing wich led to another error that was thrown when refreshing the app, the same error occured, missing columns.

As i said my coding skills are basic so the mistake is obviously on me, I just don’t know where. I would apreciate if you could tell me the normal order of doing those things :slight_smile:

Oh, the whole code (the same API requests) and plots works fine in a jupyter notebook so I guess that callback is what fails.

Thanks.

Can you post the rest of the callback function code as well, especially the “return” part of it? That drives whether your app will work correctly or not. Form what I gather, your app has some charts to show player statistics and you want to update all those charts with a specific player’s info when the button is clicked.

Sure, take a look at it here:

If you want run the app (download the json file as well) and input my ID: 208384895

Warning: The app may burn your eyes XD, but for now I couldn’t finish it the way i would like to.

I’m still not clear what’s “not working” for you. Here’s what I see when I run your app with your ID:

Yes, this version works, sorry for the confusion. The problem I had was not being able to add a dropdown and chart for top 10 heroes. If you look into the jupyter notebook file in this repository you can see it in the last cells. I didn’t know how to add that into the callback because that was an error saying that the dropdown menu in the layout is not found (because the info gets downloaded in the callback later) so I’ve diced to change that simply to the list of all the heroes that I define before the app but then it got messy. All kinds of errors started to show. I think I messed up the part with function arguments but suddenly the json part was wrong, scalar values problems appeared, the DataFrame had to be made into dictionary and all kind of other errors. If you would be so kind and tell me where I have to place another Input (above or below the current input line?) and the argument in the function (the order of arguments) I would appreciate it.
Thank You for your help.