Reformatting data in server module for client

Hello,

I need to reformat data retrieved from a table before sending it back to the client for display in a repeating panel. I haven’t found a worked example in the docs or tutorials that does this though, and I’m not sure I understand how to create the dictionaries in the correct format.

ie.

@anvil.server.callable
def get_entries():
entries = app_tables.entries.search()

for row in entries:
# add each field in row to new_dict, reformatting some fields
# add new_dict to list
return list

If anyone has worked code to point me towards I’d appreciate it.

Thanks!
Ken

Hi there. Just in case it helps, you can return the row objects to the client; however, to reduce server call overhead, you can return a list of dicts instead. You would, as usual, have to bind those to your UI properties when displaying of course.

Here is an example of making a list of dicts. The linked posts have helpful info too.

Thanks for the link. That gives me a better understanding, but for my application I’d like to reformat some of the fields as the rows / dicts are being built. For example, converting a datetime field to a text string. I know how write the reformatting code, just not how to selectively do it to certain dict fields like in the rows = [dict(x) for x in rows] example.

In general, I return the rows to the client and do the formatting on the client side in the data bindings. But, if you want to do that on the server and return a list of dicts, you’ve got the basic structure of it already. Here’s an example from my project.

  test_links = []
  
  for item in items:
    test_link = {}
    
    test_link['progress'] = item['stage']['title'] if item['stage'] else "Not Started"
    test_link['last_accessed'] = item['last_accessed']
    test_link['link'] = get_play_link(item['order_item_id'])
    test_link['description'] = item['message']
    test_link['id'] = item['order_item_id']
    test_link['mystery_id'] = mystery['mystery_id']
    test_link['plays'] = item['plays']
    
    test_links.append(test_link)
1 Like

Yep. As @jshaffstall mentions, you are in control of how you build your list of dicts. Use a loop and go for it!

Thank you both, that’s exactly what I was looking for.
Cheers!
Ken

I tend to create a ‘serialise’ function when I need that sort of thing. e.g.:

def serialise(row):
    return dict(
        progress=row['stage']['title'] if row['stage'] else "Not Started",
        last_accessed=row['last_accessed'],
        link=get_play_link(row['order_item_id']),
        description=row['message'],
        id=row['order_item_id'],
        mystery_id=mystery['mystery_id'],
        plays=row['plays'],
    )


@anvil.server.callable
def fetch_things():
    rows = app_tables.things.search()
    return [serialise(row) for row in rows]
4 Likes

Owen, that is a very elegant solution. Thanks!
K.

1 Like

I don’t think I’ve come across a more helpful and quick to reply user forum. Another reason I’m loving Anvil! Thank you all!
K.

2 Likes

Obviously, having multiple Campbells as members only improves the quality of the community!

2 Likes

Actually, these days, I tend to use the Anvil ORM library to handle this stuff.

For when I need something with some logic or related to linked rows, I simply add a property to the model class to handle that. e.g. something like:

@model_type
class Stage:
    title = Atrribute()


@model_type
class Thing:
    last_accessed = Attribute()
    description = Attribute()
    plays = Attribute()
    stage = Relationship(class_name="Stage")

    @property
    def progress(self):
        return self.stage.title if self.stage else "Not started"
1 Like

Yeah…we are pretty great :wink:.

But seriously, I agree from personal experience too. The folks around here are very helpful.

I am half Campbell - does that count :joy:

Oh, definitely!!! You reckon we count as a clan yet?!

1 Like

Hi @alcampopiano
I was reading your answer and I take the opportunity to ask and learn something new.

You say:

you can return the row objects to the client; however, to reduce server call overhead, you can return a list of dicts instead

I thought passing the rows object, being an iterator, prevents from fetching all the rows at once hence reducing the call overhead. Then anvil Datagrid component handles nicely the pagination and everything.

Passing a list of dicts might be lighter for searches returning few rows, but not if the search returns a lot of rows, isnt’it?

Thanks

Hello. There is no “one size fits all” solution. There are trade offs to consider (speed of running app, speed of prototyping, etc…). The linked posts in my comment lead to many posts that describe the trade offs between using the row objects vs returning a list of dicts.

Of course, just because you return a list of dicts, doesn’t mean you have to return all rows at once. You will always have the power to roll up your own pagination and/or limit the number of returned rows. There are pros and cons to each approach and it is worth understanding the linked posts so that you can choose the right option for you.

2 Likes