Can't load LazyMedia image from database to image component source property

Hello people

What I’m trying to do:

I’ve populate a “users” database with some information and, most importantly, pictures of each user. At each start of a session, all important data are loaded from various databases (users, vehicles, …) in a dictionnary, in the server, and transfered to a global variable to the client.
In a “USER_CARD” form, i load every user info (along with the picture, which btw is loaded as a LazyMedia) and populate my components (labels, textboxes, …) with these data from the dictionnary. Everything is populated except for the image component. When i set the image.source = the LazyMedia of the picture, i get this error:

ExternalError: TypeError: Cannot read properties of undefined (reading ‘manager’)

What looks weird is that every other info from the global dictionnary (and hence from the database) is well populated, except this one. Also, when i print the global variable containing this picture, it says it is an anvil.LazyMedia so obviously the media exists in the global variable.
It’s when i want to set the image component source that i get the error.

What I’ve tried and what’s not working:

In other forms, i’ve did exactly the same thing but never had this problem. For instance, i have a VEHICLES form that i created CARDS custom component for. On each card, there is lots of components to display each vehicle information. This includes an image component, which source is also populated with a LazyMedia from the global dictionnary that was populated at the start of the session from the “vehicles” database.

Code Sample:

This is the form USERS where i want to have all the user cards :

class USERS(USERSTemplate):
    def __init__(self, **properties):
        self.init_components(**properties)
        temp_users = copy.deepcopy(GLOBAL_VARIABLES.global_data['users'])
        self.users = []
        for id, user in temp_users.items():
            user['_id'] = id
            user['alt_agencies'] = [agency['name'] for agency in GLOBAL_VARIABLES.global_data['agencies'].values()]
            user['alt_roles'] = [roles_map[role] for role in range(3)]
            self.users.append(user)
            
    def form_show(self, **event_args):
        """This method is called when the form is shown on the page"""
        # create user cards
        for user in self.users:
            card = USER_CARD()
            card.user = user
            if user['role'] == 0:
                self.flow_panel_1.add_component(card)
            elif user['role'] == 1:
                self.flow_panel_2.add_component(card)
            else:
                self.flow_panel_3.add_component(card)

and this is the USER_CARD form which is used to create each user card. The error points to the last line, where i populate the image source.

class USER_CARD(USER_CARDTemplate):
    def __init__(self, **properties):
        # Set Form properties and Data Bindings.
        self.init_components(**properties)

        # Any code you write here will run before the form opens.

    def form_show(self, **event_args):
        """This method is called when the form is shown on the page"""
        # populate elements
        self.button_delete_1.db_name = 'users'
        self.button_delete_1.id = self.user['_id']
        self.text_box_email.text = self.user['email']
        self.text_box_phone.text = self.user['phone']
        self.text_box_first_name.text = self.user['first_name']
        self.text_box_last_name.text = self.user['last_name']
        self.drop_down_2.items = self.user['alt_roles']
        self.drop_down_2.selected_value = self.user['role']
        self.drop_down_2_copy.items = self.user['alt_agencies']
        self.drop_down_2_copy.selected_value = self.user['agency']
        self.image_1.source = self.user['picture']

I first tried with data binding. However, since i didn’t have this problem with the VEHICLES for instance, and back then i didn’t implement data binding with the vehicles, i thought the problem was the data binding and the timing of it. But i got exactly the same problem in both cases (data binding VS populating on form show event).

I suspect the issue is the deep copy
the lazy media being deep copied is not supported.

We could probably support that, but at present, when you deep copy the lazy media object, it loses some internal state, and you get the error you’re seeing.

You can probably avoid a deepcopy here with something like

global_users = GLOBAL_VARIABLES.global_data['users']
self.users = []
for id, user in global_users.items():
    user = dict(user)
    # rest of code as before


If you really want to use deepcopy, you could probably monkey patch __deepcopy__ so that you’re current code works. But worth noting monkey patching is not recommended.


def __deepcopy__(self, memo=None):
    return self

# anvil.LazyMedia is a subclass of anvil.Media
anvil.Media.__deepcopy__ = __deepcopy__

Yup, works like a charm !
I’m glad i finally posted this on the forum, been looking for this a whole day, and given the solution, i won’t have find the answer without your help.
Thanks again !

1 Like