What I’m trying to do:
I am trying to update my customer data table with changes made by user without giving browser (Forms) access to the table.
What I’ve tried and what’s not working:
I’ve written all the necessary code within the server module. I am just the relevant row of customer data to the authenticated user without issue. But I cannot seem to send the row back to server and update without full permissions (which I don’t want to give).
The error code is:
anvil.server.InternalError: Permission denied: Cannot write in table ‘Customers’ from client code.
while setting self.item[‘name’] = self.name.text
in a data binding for self.name
I know a way to get around this but I don’t think I should have to do it. Can someone point out what my mistake is?
Code Sample:
# this is a formatted code snippet.
# paste your code between ```
def edit_click(self, **event_args):
customer_copy = self.item
“”“This method is called when the button is clicked”""
save_clicked = alert(content=addCustomer(item=customer_copy),
buttons=[(‘Save’, True), (‘Cancel’, False)]
)
if save_clicked:
anvil.server.call(‘update_customer’, self.item, customer_copy)
pass
@anvil.server.callable
def update_customer(data, new_data):
if app_tables.customers.has_row(data):
data.update(**new_data)
else:
raise Exception(‘Customer does not exist.’)
Clone link:
share a copy of your app
This is your clue as to what’s wrong. You have a data binding that’s trying to write back to the table. When you’re updating on the server, you want to uncheck the write back box in the data bindings.
3 Likes
I knew it was something like that. Thank you!
1 Like
@jshaffstall when I uncheck “write back” the data in the fields no longer gets appended to my dictionary I am using to store the items. Is is possibly a bug? I am using the same form to both add and edit, and just populating the form with a copy of the data from the row. Maybe I need to somehow convert the data in the dictionary from a row to an actual dictionary, but I feel like I shouldn’t have to do that…
You don’t show how you’re populating the form, so it’s hard to say.
But, if you want to use write-back to capture the user’s changed, you do want to convert the row to a dictionary, set self.item
to that dictionary, and then have write-back checked.
The other main option is to build the dictionary in your save function, e.g.:
if save_clicked:
anvil.server.call(‘update_customer’, self.item, {'name': self.name.text, 'address': self.address.text})
In that case you’d put your row in as self.item, and have write-back unchecked.
1 Like
@jshaffstall Okay that matches how I am doing it now. I am writing the row to a dictionary, which works. Just thought a way might exist to easily cast a “Row” object to a “dict” object and save some lines of code.
self.item = dict(row)
should work. I’m not sure how you’re doing it now.
1 Like
@jshaffstall best news of day award goes to you. I wrote a complex dict comprehension to take the self.item keys and make them key values/write data keyed to them. That gets rid of that process, which is perfect.
1 Like