I want to create a function for an app that will be used as a dependency for other apps. It would have a function like this:
app_tables_dict = dependency.get_app_tables_dict()
# app_tables_dict would be something like:
# {'my_table_1': ["column_a", "column_b", ...]}
For each app the function would return something different, specific of that app.
So, I don’t need a list of app, I need a list of tables in an app. And this list is not of one unique app, but any app that runs the dependency function.
It needs to be dinamically. I can’t download the app and check the files because I would need to do that for each app and store it manually. I would also need to redo that evertime I add a new table. It would be easier to just manually type it in another table or as an enum, but that’s not what I want.
To be honest, what I want to do is something like:
d = {}
tables_in_app = app_tables.list_tables() # get a list of tables
for t in tables_in_app:
d[t] = t.list_columns()
return d
You go to the button that allows you to download the app in the ide (sorry, still on the cell, I can’t right now), right click, inspect, and check the url. I’m pretty sure that url includes the app id.
In the dependency app, you replace the app id in that url with the id of the app that is running, so you have the url to download your app. You can get thecurrent app id dynamically, Idon’t remember how, I’ll let you know when I’m at the computer.
Then, in the function, you sign in to you Anvil account, you can see the url for signing in by manually signing in. Then, once the function has signed in, you use the url for downloading (after replacing the app id), download the app and dig in the downloaded goodies.
So the goal is to get the schema at runtime because the app, and its schema, is not known in advance. This routine could be used in hundreds or thousands of apps, each of which will have its own set of tables.
There is probably some code buried in the Anvil Uplink package, that might be able to get a list of tables. That’s probably stable, for backwards compatibility, but it’s not documented or supported.
I also seem to recall a way to get the list of columns from a table… Yes. It’s in the API reference as list_columns().
Ok, reading this other topic I now understand better what you meant. That’s a little to much work than I was expecting, but also gives me a lot more info. I’ll take a look at this for the time being. Very interesting info there. Didn’t know you could do that.
Yes, exactly this.
That’s what I tought, but couldn’t find anywhere in the docs and couldn’t think of another way to do so. I posted here since, if there was a way, some of you would know (and I was right, using @stefano.menci 's method).
Yes, that’s from the Postgre’s data objects, but I don’t have direct SQL access, unfortunatelly.
̶T̶h̶i̶s̶ ̶i̶s̶ ̶t̶h̶e̶ ̶u̶n̶s̶u̶p̶p̶o̶r̶t̶e̶d̶ ̶a̶n̶s̶w̶e̶r̶ ̶t̶h̶a̶t̶ ̶w̶o̶r̶k̶s̶ ̶a̶n̶y̶w̶a̶y̶. EDIT: DONT DO THIS, USE THE NOW SUPPORTED METHOD ANNOUNCED BY STU 7 POSTS DOWN
def get_list_of_tables_in_app_with_cols():
# Only works from inside a server module if you have a 'Users' table.
return { k: [x["name"] for x in v.list_columns()]
for k, v in
anvil.server.call("anvil.private.tables.get_app_tables").items() }
Use at your own risk, ymmv, objects in code may be closer than they appear, etc. etc.
Edit: Look 7 posts down!
You should not be able to, irrc it passes the call to a Clojure method that uses the the app id to query the anvil database directly in postgres and returns all of the tables as table objects with their names.
It’s what gets called when the server module spins up to build the attributes for the app_tables object.
Since you can’t change the internal app id, you can’t get other tables. If I had to guess, ‘linked tables’ just means the table is assigned with more than one internal app id, so it would also just show up as accessible to the ‘current’ app id.
I am also unsure if this will work once they move to accelerated tables (tables.v2) as standard. There is a private method called "anvil.private.tables.v2.get_app_tables" but I am unsure if it works the same way.
I also could be completely wrong about how it works at all because I might not understand Java/Clojure as well as I think.
This is awesome! I know it’s unsuported / undocumented and should be used with caution, but that’s exactly what I needed!
I just tested this by adding the method to a server module in the app dependency and called from another app. It worked as if used natively by the running app.
I also tested the same method in an app with accelerated tables activated. Don’t know if they will change something in the future, but it worked as intended.
Thanks for testing it, I don’t have accelerated tables turned on on this app i’m testing.
I will say, if you are just using it to get the table names like I did above, that’s totally fine.
However if you have accelerated tables turned on, just make sure you don’t use the ‘table’ objects returned as the values of "anvil.private.tables.get_app_tables".
If you tried to use them with accelerated tables turned on you may get aberrant behavior.
(I talked to Stu about this once and it started to get wonky real fast)
Thanks for the tip.
The idea is to just get the names and, later, maybe use those names with getattr(app_tables, name_from_the_request) to do other things. So the usage of the tables will still be on documented anvil functions.
and if you’re using accelarted tables we support subscript notation, and introspection
for table_name in app_tables:
my_table = app_tables[table_name]
# if not using accelerated tables
# getattr(app_tables, table_name)
print(dir(app_tables)) # includes table names