[SOLVED] Setting db & field dynamically

Hi, I want to dynamically set the db & field in the search function.

I want to do something like:

db_name = ‘customers’
db_field = ‘surname’
value = ‘Smith’

app_tables.db_name.search(db_field=value)

Here is your one liner:

getattr(app_tables, db_name).search(**{db_field: value})

Here is a little explanation.

You use the built-in getattr() function when you know the name of the attribute at runtime. These two are equivalent:

db_name = 'customers'
table = getattr(app_tables, db_name)

table = app_tables.customers

In Python you can use * to expand a list of positional arguments and ** to expand a dictionary of named arguments. The search() method expects you to name the columns as named arguments, so you can create a dictionary with the named arguments and expand it in the call with **. These two are equivalent:

db_field = 'surname'
value = 'Smith'
dic = {db_field: value}
table.search(**dic)

table.search(surname='Smith')

ADMIN EDIT: Use getattr() instead of __getattr__(). Explanation below! --Meredydd

2 Likes

Thanks a million.
Er, what exact background knowledge area did you extract that from? :slight_smile:
Anvil docs? Python? OOP in general? What? Clue me in. I want to know where what I don’t know is located . .

The short answer is Google is your friend. The problem is knowing what to Google.

The Anvil documentation doesn’t teach you Python, but you can start asking in this forum, especially when you don’t know if there is an Anvil specific answer or not, like in this case. As you learn Python and Anvil, you will learn also how, what and where to ask your questions.

Stackoverflow.com is the best place for generic Python questions. Usually I start writing the question, creating small examples to put in the question to make it easier for whomever is trying to answer, and often this process alone helps me find the answer. Before posting the question I also check the links to similar questions that automatically pop up on the side.

If I need more details after Stackoverflow, I usually jump to the official Python documentation or any other googlable source. I don’t have any must go place.

For example, after getting an answer like this I would start googling “python magic methods” and “python args kwargs”. Try and you will find tons of yummy stuff about Python.

1 Like

I guess

magic method
args kwargs

is what I didn’t know to search for . .

Hi all,

I’m glad you’ve found the answer here! Just a heads-up: the correct Pythonic way to do this is the getattr() function - eg getattr(app_tables, table_name). I’ve edited @stefano.menci’s examples to reflect this.

(Not every object has a __getattr__ method - the fact that this is how we implement app_tables is a detail you shouldn’t rely on. getattr() is the fully generic way of doing what you want to do here!)

3 Likes

Hi @stefano.menci
very useful information, thanks.
I am trying to list at runtime all existing tables so the user can pick up the one he wants to act onto, do yo.
Since you got a table instance with a getattr() call, I thought a dir(app_tables) would show all tables as attributes of that object.
But a print(dir(app_tables)) shows only: [‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattr’, ‘getattribute’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘cache’]

So, how did you know that calling getattr(app_tables, <table_name>) would return the table object?
And have you a clue for me on how to get the listing of the tables?

Thanks

getattr returns the value of an attribute.

dir returns the list of attributes for an object.

They both work well out of the box, but if the class defines the magic methods __getattr__ and __dir__ you could get unexpected results.

It’s common for an object to define __getattr__, so you can use it as if it had attributes that are not defined in the class. It’s less common for that object to define and maintain __dir__. Sometimes the lack of __dir__ magic method is a message for you, the developer is trying to tell you “please don’t mess up with this”. And sometimes the __getattr__ needs to try to get the requested attribute, doesn’t know the list of available attributes.

I don’t know why app_tables doesn’t give you the list.
I have an app that allows to pick a table, but I have also a manually maintained table with the list of pickable tables.

Another solution is to go down this path, but it’s going to be tough: Programmatically access data about my Anvil apps - #4 by stefano.menci

2 Likes

If you save a backup of your app, as a .yaml file, you’ll find it contains a line
exported_table_schema:
Your table definitions immediately follow that line.

A yaml parser will make short work of finding and accessing the table definitions.

Note: this is undocumented territory, subject to change without notice.