for medicine in medicines:
m = MedicineItem(name=medicine['name'], image=medicine['image'], price=f"{medicine['price']}", description=medicine['description'], button_callback=self.render_add_to_cart)
self.content_panel.add_component(m)
It looks like you may be assuming that row is a single variable, passed by reference. In other languages, that’s a perfectly reasonable assumption. But here, it isn’t, for several good reasons.
First, get_all_medicines runs on a completely different computer from anvil.server.call. The computers aren’t sharing memory. So get_all_medicines can only receive a copy of row's value.
Second, in Python, the variable row that exists inside get_all_medicines is a completely separate variable, local to that particular call of get_all_medicines. As a result of the call, it initially points to the (received) copy of the value of caller’s row. Then, as a result of assignment, it no longer points to that copy, but points to the result of your app_tables.products.search call. After that, local variable row ceases to exist.
Either way, the in-browser variable row, whose value is passed in to the anvil.server.call, isn’t going to change. That’s an entirely separate variable.