I'm really not getting how to update a data table row

I’m really struggling with getting my head round updating a column in a single row. Now I’ve tied myself up in knots! It should be simple but I’m not getting it.

so, I have a row in a repeating panel. I want on a button click event to update that row and set the boolean value of a column in that row to True. I’m sorry for my poor effort but here it is.

  def button_1_click(self, **event_args):
    """This method is called when the button is clicked"""
    self.msgsubject_detail.visible=not self.msgsubject_detail.visible
    set_read = {
      "Read": True    }
    anvil.server.call('update_user_msg_read',set_read)
    pass
@anvil.server.callable
def update_user_msg_read(set_read):
  row =app_tables.usermessages.get(Read=False)  ##I Dont even know what to put here
  Row['Read']=set_read

Start from the end:

You need to update a row of a table:

row['Read'] = ...

You need that ... and you need that row:

row = app_tables.usermessages.get_by_id(row_id)   # use this if you use the default row id created by Anvil
row = app_tables.usermessages.get(row_id=row_id)  # use this if you want to identify the rows with your own unique column
row['Read'] = value

You need row_id and value:

@anvil.server.callable
def update_user_msg_read(row_id, value):
  row = app_tables.usermessages.get(row_id=row_id)own unique column
  row['Read'] = value

You need to provide those values:

def button_1_click(self, **event_args):
  anvil.server.call('update_user_msg_read', row_id=row_id, value=True)
  anvil.server.call('update_user_msg_read', row_id, True)  # this is equivalent, to the previous, use whichever you like

Now the question is where do you get row_id or whatever identifier will allow you to get your row back from the database when you need it.

If you are inside a repeating panel, it should be something like self.item['row_id'] or self.item['email_address'] or self.item['name'] or… you get the gist.

If you are not inside a repeating panel, then… well, it depends on where you are.


The point of this answer is not to give you a direct answer to this very question, it’s more to give you a thought process so you can find the answer yourself.

Sometimes it’s easy to think “I made it this far, let’s see what’s the next step with what I already have”

But sometimes it’s better to think “That’s where I want to go, let’s see what I need to get there and let’s make sure I have it on all the steps that will lead me there”

3 Likes

Thanks Stefano, you are right about the thought process, I guess you can see from my post here, I was doing more damage than anything, in reading something, changing it and then changing other bits…

You are also right, its the ID thats been bugging me, I did try to create a label called ID in the repeating panel and assign self.item[‘ID’] to it, but it said it didnt exist, well of course it does but its accessing it. I’ve always used SQL Tables so that might explain my want of a primary key, with a number I can see - and use!

Thanks so much for the reply, I’m sure I will crack it now with this help!

Well here is my solution, it does work, but not sure its as pretty as it should be :slight_smile: (the print statements are there so I can just check its working) I think I get you now, the key can be any one of the self.item in that row.
client code:

  def button_1_click(self, **event_args):
    """This method is called when the button is clicked"""
    self.msgsubject_detail.visible=not self.msgsubject_detail.visible
    row_id = self.item['Created']
    print(row_id)
    value = True
    anvil.server.call('update_user_msg_read',row_id ,value)

Server Code

@anvil.server.callable
def update_user_msg_read(row_id,value):
  row = app_tables.usermessages.get(Created=row_id)
  value = value
  print(row)
  print(value)
  row['Read']=value

If you are sure that you will never have two rows with identical self.item['Created'], then this works.

I find it more readable using more meaningful variable names, but that’s just matter of style:

  def button_1_click(self, **event_args):
    self.msgsubject_detail.visible = not self.msgsubject_detail.visible
    anvil.server.call('update_user_msg_read', self.item['Created'], True)

@anvil.server.callable
def update_user_msg_read(created, value):
  print(f'update_user_msg_read({created}, {value})')
  row = app_tables.usermessages.get(Created=created)
  row['Read'] = value
1 Like

Thanks for the tidier code, that helps. Created is a timestamp so I think its probably about as unique as you could get it, but I’d still prefer to use the actual row id. Is there any way to bind a field to the row id on the clientside?? Or would I have to create my own UID?

How do you get the row and pass it to the client?

1 Like

Hi, with self.item[‘myfield’] Apologies if I am getting confused. It just made me think that wasnt correct.

I’m asking how you get the row from the database to the client.

I create a server function, that gives me all the rows, then I use a self. that calls that server function into a repeating panel or from there I can isolate a certain field.
Most of mine are search() or restricted to current_user. They are pretty basic.

Can you please show me?

You say self.item[‘myfield’], but if you don’t tell me what’s self.item, I don’t know how to help.

So here is the server code

@anvil.server.callable
def get_mystuff_for_user():
  user = anvil.users.get_user(allow_remembered=True)
  return app_tables.mystuff.search(User=user)

So here is one
self.repeating_panel_manage.items = anvil.server.call('get_mystuff_for_user')
And then I use data binding within the Design UI to set the self.item, so for example one of those data bindings is self.item['MyStuffName']

Well… it looks like self.item contains a row object.

Then all of the above does not apply.

All you need to do is:

def button_1_click(self, **event_args):
    self.item['Read'] = True
2 Likes