I’m trying to update a single row in the database using “write-back”.
I have sensors sending temps back to an anvil API, then into the DB. Also setup users, so for now I’m using the logged in user to query the sensor/setup data.
class Setup(SetupTemplate):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run when the form opens.
#make db call to get setup data. allowing writing and up dating to the db
#get the logged in user first
self.getSensorData()
def getSensorData(self, **event_args):
print(f"This user has logged in: {anvil.users.get_user()['email']}")
logged_in_user = anvil.users.get_user()['email']
getSetupRow = anvil.server.call('getSensorSetupData', logged_in_user)
self.room_name_text_box.text = getSetupRow['sensorname']
self.desired_humidity_text_box.text = getSetupRow['targetedhumidity']
self.desired_temp_text_box.text = getSetupRow['targetedtemp']
self.light_type_dropdown.selected_value = getSetupRow['lightType']
self.leaf_temp_offset_text_box.text = getSetupRow['leafoffset']
What am I missing? I’m setting the self.item[‘sensorname’] write back to match the table name in the database. It pulls info ok, but doesnt save/write-back.
Your forms don’t have permission to write to the table. Look in your db table at the Permissions section. Forms are currently set to no access.
Note that using write back is not secure at all. It might be fine for some applications, but for more security you want to call a server function to save to the data table.
The “writeback” checkbox is for writing the value back from the form to the named variable. What you do with the resulting variable is up to you, i.e., to your code. Anvil has no way of knowing which of a thousand things you might want to do with the value after that.
Right now, it looks like you are making an assignment to the text property in getSensorData. That’s not how data-bindings work: They bind the attribute to a python reference, and the assignments you are making (i.e. self.room_name_text_box.text = row['sensorname']) are just that: One-way simple assignments of a string to the attribute self.room_name_text_box.text.
So, to use bindings, you have to assign to self.item and refernece that (your reference in the binding looks correct). So simply replacing your function with:
def getSensorData(self, **event_args):
print(f"This user has logged in: {anvil.users.get_user()['email']}")
logged_in_user = anvil.users.get_user()['email']
getSetupRow = anvil.server.call('getSensorSetupData', logged_in_user)
self.item = getSetupRow
# and bind all your component attributes to keys in self.item
Should just work.
Worth noting that self.item is kind of special, but it’s not magic - you still need to tell Anvil what self.item references. (This often happens for you in repeating panels and such.)
Edit (for completeness):
Actually (in the case of repeating panels) it’s just that the assignment to self.item is occuring in that init_components call. Note that in that case you can get the item earlier from properties["item"], so I’m assuming that all that’s happening in the init_components call is self.item=properties['item']!
– So, to use bindings, you have to assign to self.item and refernece that (your reference in the binding looks correct). So simply replacing your function with
This is what I was wanting to accomplish but wasnt sure how to connect the self.item.
the self.item = getSetupRow is what I was missing.
I decided to just write a server module and pass the data back to it, then have it do the deleting.
This project is for esp32 temp sensors in our greenhouses and I’m using the anvil API to POST the data back to the app.