'NoneType' Does Not Support Indexing

I’m trying to create categories for an ecommerce site. But I keep getting an error saying TypeError: ‘NoneType’ Does Not Support Indexing.

I’ve tried to data bind the name, image, price, and description to the table, but I still get an error.

def update_form(self, category_row):
medicine = anvil.server.call(‘get_medicine_details’, category_row)
self.name_label.text = medicine[‘name’]
self.image_content.source = medicine[‘image’]
self.price_label.text = f"${medicine[‘price’]}"
self.description_label.text = medicine[‘description’]

https://anvil.works/build#clone:QYMBON3FCI6GPUUL=66EOLRYQSWUNC2U5BGH6GJZI

This is a very common Python error, caused when you use a variable as a list or dictionary, but the variable’s value is None.

In your case, you never return anything from your get_medicine_details server function. Python functions that do not have a return statement return the value None.

4 Likes

I am returning something in this example here:

@anvil.server.callable
def get_medicine_details(medicine_name):
return app_tables.products.get(name=medicine_name)

The value being returned is None. Since you are returning something from the function, it follows that what’s being returned is None.

The get function returns None when nothing matches the criteria. In your case, you are passing in a string with all lower case, but what’s in the data table is mixed case. The = operator for comparing strings is case sensitive.

To debug this sort of thing, put print statements in your server code to see what you’re actually passing in, and then look at your data tables to see what’s in it.

3 Likes

I don’t quite understand what you mean. Do you mean the actual data is mixed case? Can you please clarify?

Do the above. Look in your data tables to see what is in the name column in the Products table.

Do a print of medicine_name in your server function.

1 Like

When I do the print statement of medicine_name, the actual name of the medicine is printed, but the error still appears.

Are these two strings identical? Or do they differ in any way, e.g., in capitalization?

@anvil.server.callable
def get_medicine_details(medicine_name):
return app_tables.products.get(id_name=medicine_name)

def update_form(self, id_name):
medicine = anvil.server.call(‘get_medicine_details’, id_name)
self.medicine = medicine
self.name_label.text = medicine[‘name’]
self.image_content.source = medicine[‘image’]
self.price_label.text = f"${medicine[‘price’]}"
self.description_label.text = medicine[‘description’]

hi @cantony2 - like @jshaffstall points out - some debugging print statements would really help here.

The return value from

return app_tables.products.get(id_name=medicine_name)

is returning None - because no Row matches your query.
To debug you might also raise an error when you want your code to fail loudly

@ anvil.server.callable
def get_medicine_details(medicine_name):
    rv = app_tables.products.get(id_name=medicine_name)
    if rv is None:
        raise LookupError(f"no table found with id_name={medicine_name!r}")
    return rv

Adding that line gives the following error:

LookupError: no table found with id_name='adult robitussin maximum strength medicine'

Your id_name for that product is "adult_robitussin", so what you’re passing the function doesn’t match.

If you want some more logging anvil_extras just added client and server side logging that can be used for things like this.

from anvil_extras import logging
server_logger = logging.Logger("server_logger", level=logging.DEBUG)

@ anvil.server.callable
def get_medicine_details(medicine_name):
    rv = app_tables.products.get(id_name=medicine_name)
    if rv is None:
        server_logger.debug(f"None returned from product table id_name={medicine_name!r}")
    return rv
1 Like

But I’m trying to when the customer clicks on View Details on a certain product, in this case, medicine, it will bring up the medicine’s name, image, price, and description. I’m not trying to retrieve just one medicine or product, I’m trying to retrieve any medicine or product. Does this mean I have to hard code every product to equal the id_name?

If you want

to find the matching product, then the match must be exact. It’s not going to attempt to second-guess what the author “meant”, or read minds, or fuzzy-match, or any of those unreliable approaches. That’s how this particular machinery works.

That said, depending on what you want to achieve, there may be other database features that are a better fit.

Do you mean “every matching medicine or product”? If so, then how do you define “matching”? The answer can guide you towards the right database features.

2 Likes

Line 25 in your MedicineItem component is making the text you are searching the table for, all lower case. This happens before it submits it up your chain of functions to the table search.

There is no match to the lower case version of that medicine name.

self.button_callback(self.name_label.text.lower())

This was not easy to debug because it is being passed around so many times, and many of the functions are named the same or similar.

Also, this is incorrect.

Doing this:
image

Results in:
image

“adult robitussin maximum strength medicine” is not the same as “Adult Robitussin Maximum Strength Medicine” as @p.colbert already pointed out.

image

As @jshaffstall said at the beginning, the result it is returning is None because your search returned no results.

I found this yesterday, but I was hoping you would also find it, since just giving you the answer doesn’t really allow you to learn anything.

3 Likes