What I’m trying to do:
I am trying to allow users to sign up and sign into my app immediately. However, my app requires access to 3 existing ‘workspace’ data tables ‘assigned’ to each new user in my user table when they sign up. For example, User1 has access to table_13, table_14, table_15, while User2 has access to table_16, table_17, table_18, etc. Currently, I’m in beta so manually assigning tables to new users.
However, when new users signs up using the ‘Register’ link, it creates a brand row in the user table with empty ‘workspace’ cells. I need it to actually assign the next blank cell in the column, not an entirely new row.
“Best” is in the eye of the beholder, but here’s an idea…
When they first sign in, check for blank entries. If the entries are blank, then fill them in.
Keep a separate, one-row table, to record the last table number used.
Just in case two people first log in at the same time, use a database transaction to
a. Fetch the last table number
b. fill in the columns.
c. update the last table number.
I don’t want this to be sound like I’m saying you are “doing it wrong”, I just want to point out:
This is clunky, and you should just avoid doing it this way at all costs.
You should probably all be using the same tables with the first column containing the users email, and all reads and writes should be done to a view of the table that matches the email contents of anvil.users.get_user() (From within the server module so no client code)
This way you only have one table with the different users data interleaved in the back-end, but inaccessible to each other. This would have no user “set up” for each new user. (Beyond maybe clicking an “enabled” box in the users table, or something.)
I have to agree. Anvil currently has no way to create tables programmatically. Every time a new user signs up, you’ll have to create three tables manually. That gets old (and buggy) really fast.
Views are vastly safer, can be created server-side, on-demand, and are intended to solve exactly this problem.
Still do this. (I mean replace a and c with however you want to store your data, but use transactions)
If the reason why you think you want separate tables for each user is that they will have data with differently named “columns” of data to be stored, you probably actually want to use key/value pairs in one or more object columns to store the data.
I appreciate the advice. Being how this was my first app, I made a few mistakes off the top in terms of memory, table access, and understanding how users would sign up. I’m aware it’s clunky, but this is where I’m at unfortunately. This is pretty much the last stage before I launch this app, so I’m looking to simply solve the problem as is.
I think what I’ll end up doing is saying "if a new row has been added to this table, go and find the first instance of “new_user_here”, take all those tables and assign them to that user email.
When I started, I didn’t have the background to understand views. Even now, after 6 months of anvil development, I have a hard time understanding how to use it.
This is how I access and save user variables now. I didn’t save variables as objects / key value pairs / or as a dictionary, instead it was just straight text values.
A View is a well-defined “slice” of a table, consisting of exactly those rows where a given column has a given value. You tell Anvil which column should have which value, and it hands you the corresponding View.
Rows obtained from the View omit that column, since its value is already known. Likewise, if you use that View to create a Row, it will supply that known value for that column.
In this way, you can give each user their own private “slice” of a table: e.g., the rows where row['owner"] == company_name.
Create your extra tables for a few new users in the users table with the email set to None
(Just make new entries at the bottom of the users table for this part without an email:
)
In the __init__ function of the first page of you app add a server call after the call to log in (if you do that).
In that server function that you call you will have to assign “new” users the information from one of the “None” rows, and then delete it.
for example:
def assign_new_user_workspaces():
new_user_rows = app_tables.users.search(workspace_1=None) # All Three? Why?
for user_row in new_user_rows :
# Column is Named 'user' column in app instead of 'confirmed_email'?
unassigned_rows = app_tables.users.search(confirmed_email=None)
for unassigned_row in unassigned_rows :
user_row.update(
workspace_1=unassigned_row['workspace_1'],
workspace_2=unassigned_row['workspace_2'],
workspace_3=unassigned_row['workspace_3'],
)
unassigned_row.delete()
break
This way you can create your extra tables ahead of time, assign them to None users, then have them re-assigned on the fly.
You will eventually run out of new tables for new users though and it will break.