Add/remove items from one-to-many column

Hi all! Happy new year!

I’ve been experimenting with the one-to-many (link to table > table > multiple rows) Data Tables column and was trying to figure out how to add/remove items. First, I was trying to use list operators (ie. remove, pop, append) on the column itself.

So I start out with this to get the items in the table and the row that I want to remove from the list of rows:

my_table_items = app_tables.mytable.search()
row_to_remove = app_tables.myothertable.get(name='my row')

Then I iterate through the rows, find the item to remove and then attempt to remove it using the remove() list operator.

for m in my_table_items:
  for list_item in m['my_column']:
    if list_item == row_to_remove:
      m['my_column'].remove(row_to_remove)

I also tried getting the index() and using pop():

for m in my_table_items:
  for list_item in m['my_column']:
    if list_item == row_to_remove:
      item_index = m['my_column'].index(row_to_remove)
      m['my_column'].pop(item_index)

Neither of these produced any exceptions but both failed to remove the item from the list. Interestingly enough, index() does return the correct index of the item in the list. :frowning:

So then I tried assigning the column to a local variable, performing the operation, and then setting the column back to the local variable.

for m in my_table_items:
  for list_item in m['my_column']:
    if list_item == row_to_remove:
      linked_rows_list = m['my_column']
      linked_rows_list.remove(row_to_remove)
      m['my_column'] = linked_rows_list

Boom! :sunglasses: Works perfectly. I haven’t tried append() but I assume any of the list operators would also work this way.

Are list operations that add/delete not allowed directly on the data tables list object?

I’ve also tried the first method in server code so I don’t believe permissions are an issue.

Thanks, so much!

-Kirk

2 Likes

Hi Kirk,

Apologies for making you conduct all these experiments yourself, we should improve this behaviour and document it in the meantime.

Anyway, you worked it out - “Multiple Rows” columns are not real Python lists, so don’t fully support the standard list operations (hopefully they will soon). Right now all you can reliably do is get and set the values. In particular, this will work:

m['my_column'] += [new_item]

As will this (to remove an element):

m['my_column'] = [r for r in m['my_column'] if r != row_to_remove]

Hope that helps!

5 Likes

I would appreciate some documenting of this (asking humbly as someone using Anvil for free, so far). It took me an hour or so of (noob, bungling) debugging before I realized that lists in “Multiple Rows” (or Simple Object) columns are not real Python lists, so that the append method does not work.

Correct, they do not update the database if you use append - the update occurs only in memory. I’ll document this in the Using Data Tables in Python part of the ref docs. Thanks for the tip :slight_smile:

2 Likes

@daviesian Hi,

Can you please explain how to remove a row from a column, I have tried all the mentioned methods, but no luck!

Thank you.

Not sure if I’ve misunderstood, but this is how you delete a row (taken from the docs :
https://anvil.works/doc/#data_tables_api)

# Remove Jane Smith from the table
jane_row = app_tables.people.get(Name="Jane E. Smith"):
if jane_row is not None:
  jane_row.delete()

If that doesn’t work can you post your code and the results?

1 Like

Hi @adhamfaisal, and thanks David for your example. I think this snippet from my post above is actually what’s needed here, if you want to remove row_to_remove from the column my_column:

Hope that helps!

1 Like

Thank you, it look like there was a mistake in my code.

For some reason it is not working for me, and I am having hard time understanding the code concept.
Thank you though.

I was able to figure out how to remove a row from a data table, I made a copy of the app and posted it under a new topic:

Thank you all :slight_smile:

Hey @daviesian I have also tried this code exactly, and similar to @adhamfaisal I could also not get this to work.

When run, it doesn’t actually delete the row_to_remove from the multi-value column.

Any ideas why this might be?

Are you getting an error? Please post more details if possible (clone, code).

1 Like

Hm, somehow in the process of recreating a simplified version of my current app with only this problem in it I got it to work! For future reference, here is a clone of an app with the above process implemented successfully.

https://anvil.works/build#clone:V46SDSR2DNIJ4AJF=44DV6KCY7RBI7EKWLCYPMPZW

Doing some troubleshooting, I found my error.

I incorrectly had:

m['my_column'] = [r for r in m['my_column'] if r != [row_to_remove]]

when I should have had:

m['my_column'] = [r for r in m['my_column'] if r != row_to_remove]

I think I was just being confused because when you add the new item you need the square brackets around the [new_item] but they aren’t needed when you use the row_to_remove function

2 Likes

A post was split to a new topic: LiveObjectProxy object not callable