I have a form with 2 cards on it.
Card_1 says “Start your first restaurant!”
Card_2 says “You’ve already got a restaurant!”.
I have two data tables “users” and “restaurants”.
The “restaurants” table has a column that is linked to the “users” table called “owner”.
I want to hide Card_1 and show Card_2 on form startup (or vice versa), conditionally on whether or not the currently logged in user has their row in the “users” table assigned as an “owner” to any row in the “restaurants” table.
How would I go about doing this? I have a link to a cloneable version of this.
(You can login with test@gmail.com, password: 1234)
https://anvil.works/build#clone:44KJ6SGRTPERKXWM=IXQX2XX5EAVMPO6YKHATKXF4
Perhpas on the server you could return a True or False based on the users data.
For example:
# on the server
current_user=users.get_current_user()
if app_tables.restaurants.search(user_row=user)
hide_card_1=True
else:
hide_card_1=False
Once you have returned something from the server you can use to determine which card to show, set the card’s visibility property accordingly.
Another thing you will want to do is to make sure that you are not returning any actual data to the client that you do not want exposed. So, a boolean might control some visibility property, but if a user were to change that boolean somehow, they would not see any actual data.
I hope this gets you started. Please feel free to share more code and/or details if I have misunderstood.
1 Like
This is a simplistic take on the problem (this would go into the Form1.init method)
user = anvil.users.get_user()
self.card_1.visible = True
self.card_2.visible = False
if user:
if app_tables.restaurants.get(owner=user):
self.card_1.visible = False
self.card_2.visible = True
This is not secure, and is intended only as a proof of concept to get you started. As @alcampopiano says, the data table access should really happen on the server, not the client, unless you don’t care about all clients being able to see all rows in those tables (definitely a bad idea for the user table, which contains hashed passwords).
If security is an issue, I’d never return a user table row to the client unless it’s the one for the currently logged in user.
2 Likes
@alcampopiano @jshaffstall thank you both for replying!
Okay I tried to put together what you guys suggested, but it is just returning True every time, even if the user has not been assigned to any restaurants. (Card_2 is always visible, Card_1 is always hidden)
Server Code:
@anvil.server.callable
def check_user():
current_user = anvil.users.get_user()
if app_tables.restaurants.get(owner=current_user):
hide_card_1=True
else:
hide_card_1=False
Form 1 Code (in the init function):
if anvil.server.call('check_user') is True:
self.card_1.visible = True
self.card_2.visible = False
else:
self.card_1.visible = False
self.card_2.visible = True
Could you modify your clone so we can try it?
Also, are you actually returning anything from your server function?
That is,
.
.
.
return hide_card_1
This is not the issue, but just in case you feel it is helpful, did you know that you can omit is True
in your if statement?
if anvil.server.call('check_user'):
is sufficient to test for truth.
Thank you Python!
1 Like
Here it is!
https://anvil.works/build#clone:44KJ6SGRTPERKXWM=IXQX2XX5EAVMPO6YKHATKXF4
Good point, I added the return hide_card_1 line.
And thanks for the tip about the True statement! Neat 
1 Like
Your code is working, but the logic is backwards.
Look at what you’re setting your card visibility to. When the user has a restaurant (the server call returns True) you show card 1 and hide card 2. That’s the opposite of what you want. Card 1 is the one you want to show when they don’t have a restaurant.
2 Likes
Good catch!! Fixed that. Okay I think I’m close now! Except that now if the user is assigned to more than one restaurant, it gives me an error:
anvil.tables.TableError: More than one row matched this query
https://anvil.works/build#clone:44KJ6SGRTPERKXWM=IXQX2XX5EAVMPO6YKHATKXF4
You can use app_tables.restaurants.search()
instead of get
. Note that this returns a search iterator. This may still be considered “Truthy” even if you return zero records (I can’t remember).
I guess if you don’t actually need to return the data from the table, you can just test for a length greater than zero.
len(app_tables.my_table.search())
2 Likes
Yes, you’ll want to do a search and check the number of results using len. On a mobile device right now, but check the data table docs.
2 Likes
@alcampopiano @jshaffstall thank you guys so much!! Been bashing my head against this in a bunch of different apps all afternoon. The len solution worked! Thank you so much