Model Class attributes and tabulator

Hi all,

How can one go about using Anvil Model Classes and an attribute of the model class as the data to display in tabulator?

I have a model class like this:

from anvil.tables import app_tables

class MyTableRow(app_tables.mytable.Row):
    @property
    def double_values(self):
        double_values = {
            k: v*2 for k,v in self["my_column"].items()
        }
        return double_values

On the client side I can see that the row object from my table indeed has a “double_values” property, but I can’t seem to use it as the field when definining my tabulator columns. Here is a clone link showing what I’ve tried:

You’ll notice the first table which uses “my_column” works just fine. But the second table which uses the field “double_values” raises an error stating that no such column is found. I know that indeed there is no such “double_values” column in reality, but was hoping that this attribute might be accessible when using Tabulator.

Not sure if this question is best suited here or on the anvil-tabulator Github site. Thought other users might have the same question.

So to answer my own question, I solved it with a custom getter:

import operator 

def model_class_getter(data, field):
    """
    Custom getter that tries operator.getitem first, then falls back to getattr
    """
    try:
        # First try dictionary-style access (operator.getitem)
        return operator.getitem(data, field)
    except Exception as e:
        try:
            return getattr(data, field)
        except Exception as _:
            raise e # raise the first error

The default getter in Tabulator is operator.getitem, which acts basically on a dict. However, a dict version of the row does not contain the model class attributes. So if the default fails, then try the getattr method, and if that also fails then raise an error.

This combination of getters solved it for me.

models also provide options in the form of keyword arguments

from anvil.tables import app_tables

class MyTableRow(app_tables.mytable.Row, attrs=True):
    @property
    def double_values(self):
        double_values = {
            k: v*2 for k,v in self["my_column"].items()
        }
        return double_values

Now you can change the getter to getattr instead of your model_class_getter

1 Like

I did try this originally, however this only works for columns like text, numbers etc… But anything with nested data like a dictionary where you want to access the fields with "my_dict.my_key" doesn’t work.

I have updated the clone link to show this:

Ok, try the latest version of tabulator
It should better handle nested dictionaries

Great, yes the latest version seems to work with getattr. Thanks @stucork

1 Like