[RESOLVED] Saving 0 as a value from api call

I have an API call that works 100%.
I get the data that I need, and I can save it to the table.

But when the qty in a specific item = 0, then it doesn’t save it as 0.
It saves it as an empty sell.

How do I rectify this?

I think we’re going to need more information about what specifically you’re doing to be able to help.

The zero(0) in the json results are not saving as a value.
It leaves the field in the data table empty. (2nd image).
All the results that are bigger than 0 saves 100% correctly.

Unfortunately I don’t know what else else to provide.

image
image

You could provide a clone link to an app that exhibits the issue. Or you could provide code samples showing the steps of how you’re handling the JSON and saving to the data table.

If you try saving 0 to the data table in a different way, does that work?

1 Like

Without seeing code it’s impossible to say what’s going on. As @hugetim said, a clone link would be best.

In general, though, remember that 0 is a Falsy value for Python, so if you’re doing any sort of conditional based on the value in the cell, that might be an issue.

1 Like

@hugetim @jshaffstall unfortunately I can’t share a clone link to the app.
But here are the sections of the code that’s for saving that specific data values.
The data saves without a problem when the result >0.
But as soon as it’s 0, it doesn’t save the 0

API call results

if response["status_code"] == 20000:
          for item in response["tasks"][0]["result"]:
            keyword = item["keyword"]
            locationCode = item["location_code"]
            languageCode = item["language_code"]
            searchPartners = item["search_partners"]
            competition = item["competition"]
            cpc = item["cpc"]
            searchVolume = item['search_volume']
                   
            anvil.server.call('add_keyword_results', keyword, locationCode, languageCode, searchPartners, competition, cpc, searchVolume)

Saving to the table:

@anvil.server.callable
def add_keyword_results(keyword, locationCode, languageCode, search_partners, competition, cpc, search_volume):
  row = app_tables.keyword_results.get(keyword=keyword) or app_tables.keyword_results.add_row(keyword=keyword)
  row['location_code'] = locationCode
  row['language_code'] = languageCode
  row['search_partners'] = search_partners
  row['competition'] = competition
  row['cpc'] = cpc
  row['search_volume'] = search_volume

Print the type of cpc at the moment when you’re setting it into the data table. I don’t know if passing in something other than a number would do what you’re seeing, but it’s worth checking.

2 Likes

Thanks @jshaffstall I did that with this code, print(type(search_volume))

and this was the results:
'NoneType is where the resuly was zero, and the ‘int’ is where ther was a result bigger than 0

<class ‘NoneType’>
<class ‘NoneType’>
<class ‘int’>
<class ‘NoneType’>
<class ‘NoneType’>
<class ‘int’>
<class ‘NoneType’>
<class ‘NoneType’>

That narrows down where to look, then. What’s in your API results?

2 Likes

@jshaffstall it prints out None as a result
image

What I have figured out is that the results are giving a null value because there are no data available. Lesson learned!

But should I leave this as a null value, or handle it as 0? What would best practice be?
I will be using the results in tables & graphs.

1 Like

@jshaffstall Thanks for all your help. I appreciate it.
Once I understood the problem I was able to fix it with a simple if statement.

if search_volume == None:
    row['search_volume'] = 0
  else:
    row['search_volume'] = search_volume
1 Like

That’s a good approach, since a None volume does mean 0, and it certainly simplifies graphing since you have numeric data in the data table.

Glad you got it sorted!

1 Like

you could save yourself a line or two with:

row["search_volume"] = search_volume if search_volume is not None else 0
1 Like

Thanks @owen.campbell. Makes a big difference in the code.
Appreciate it

You might save a few more lines with something like:

if response["status_code"] == 20000:
    for item in response["tasks"][0]["result"]:                 
        anvil.server.call('add_keyword_results', **item)
@anvil.server.callable
def add_keyword_results(**kwargs):
    row = app_tables.keyword_results.get(keyword=kwargs["keyword"]) or app_tables.keyword_results.add_row(keyword=kwargs["keyword"])
    if kwargs["search_volume"] is None:
        kwargs["search_volume"] = 0
    row.update(**kwargs)

if item has more keys than the server function needs, you’ll need to remove those.

You could also save the repeated server calls by passing the entire list of dicts and looping within the server function instead:

if response["status_code"] == 20000:        
    anvil.server.call('add_keyword_results', response["tasks"][0]["result])
@anvil.server.callable
def add_keyword_results(items):
    for item in items:
        row = app_tables.keyword_results.get(keyword=item["keyword"]) or app_tables.keyword_results.add_row(keyword=item["keyword"])
        if item["search_volume"] is None:
            item["search_volume"] = 0
        row.update(**item)

And, if you wrap that server function with a transaction it should run a lot faster.

2 Likes

Thanks again @owen.campbell this is getting better & better.
It solved several other obstacles for me as well.

Previously I was able to round the results & x 100.
But I haven’t been able to figure it out in your example.

row['paid_competition'] = round(float(paid_competition) * 100) if paid_competition is not None else 0

At this point, I’d be tempted to create a class and use instances of that rather than dicts. You could then use properties to handle these sorts of issue.

2 Likes

@owen.campbell I’m going to go the route of classes because there’s a bunch of stuff I want to do with the data.
But out of curiosity, is it possible to do the rounding in your example, and how would you do it?

@anvil.server.callable
def add_keyword_results(items):
    for item in items:
        row = app_tables.keyword_results.get(keyword=item["keyword"]) or app_tables.keyword_results.add_row(keyword=item["keyword"])
        if item["search_volume"] is None:
            item["search_volume"] = 0
        item["paid_competition"] = round(float(item["paid_competition"]) * 100) if item["paid_competition"] is not None else 0
        row.update(**item)
1 Like

Thanks again @owen.campbell
I can see where I went wrong when I tried to do it. Instead of saving code lines I tried to go back to my default of trying to do it with an if: elif statement.

I have learned more about Python the past two days than I did this whole month.

4 Likes