Account Links Visibility¶
Currently we have four links associated with accounts (Register, Login, Account, Logout), but the relevance of these links depend on whether the user is logged in or not. If the user is logged in, they don’t need the login or register link, and, similarly, account and logout are not needed if the user is not logged in. So we should adjust the MainForm to not display irrelevant links. How will we do this?
Planning¶
Fortunately each layout element has a visibility property, so we can simply set this to True
or False
depending on the logged in status of the user.
In testing the last tutorial we used code the anvil.users.get_user()
to show who the current logged in user was. If there was a user it returned <LiveObject>: anvil.table.Row
, if there wasn’t a user it returned None
. According to Python truthiness, any object is has a Boolean value or True
, while None
has a Boolean value of False
.
Python Truthiness
In Python, “truthiness” refers to how values are evaluated in a boolean context, determining whether they are considered True
or False
. The values that return True
are said to be Truthy, while the values that return False
are called Falsy
.
Truthy Values |
Falsy Values |
---|---|
|
|
Any non-zero number (e.g., 1, -1, 3.14) |
Zero of any numeric type (eg. |
Non-empty strings (e.g., “Hello”) |
Empty string (eg. |
Non-empty lists (e.g., [1, 2, 3]) |
Empty list (eg. |
Non-empty dictionaries (e.g., {“key”: “value”}) |
Empty dictionary (eg. |
Non-empty tuples (e.g., (1, 2)) |
Empty tuples (eg. |
Non-empty sets (e.g., {1, 2, 3}) |
Empty set (eg. |
Objects by default |
Special Objects that explicitly return |
We will use Python truthiness, get_user() and the links visibility to dynamically adjust the account links in respect to the users authentication.
We want to map it this way:
|
Register visibility |
Login visibility |
Account visibility |
Logout visibility |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
If you look at the table above you can see that the truthiness of:
Register visibility is the opposite of
get_user()
Login visibility is the opposite of
get_user()
Account visibility is the same as
get_user()
Logout visibility is the same as
get_user()
There the visiblity of the links can be rewritten as a function of the truthiness of get_user()
.
Register visibility =
not get_user()
Login visibility =
not get_user()
Account visibility =
get_user()
Logout visibility =
get_user()
Where should we place our code? It would be effective if the test is done each time the page changes. We just made a function set_active_link
which we call each time a link is clicked, so we should put it there.
Code¶
Open the MainForm in code mode and go to the set_active_link
method.
Then you want to enact our plan above by writing the highlighted code at the bottom of the set_active_link
method.
23 def set_active_link(self, state):
24 if state == "home":
25 self.link_home.role = "selected"
26 else:
27 self.link_home.role = None
28 if state == "add":
29 self.link_add.role = "selected"
30 else:
31 self.link_add.role = None
32 if state == "calendar":
33 self.link_calendar.role = "selected"
34 else:
35 self.link_calendar.role = None
36
37 self.link_register.visible = not anvil.users.get_user()
38 self.link_login.visible = not anvil.users.get_user()
39 self.link_account.visible = anvil.users.get_user()
40 self.link_logout.visible = anvil.users.get_user()
Code explaination
line 37:
will set the visibility of
link_register
to opposite of the value returned byanvil.users.get_user()
therefore if a user is logged in,
link_register
will not be visible, but if there is no user logged in, thenlink_register
will be displayed.
line 38:
will set the visibility of
link_login
to opposite of the value returned byanvil.users.get_user()
therefore if a user is logged in,
link_login
will not be visible, but if there is no user logged in, thenlink_login
will be displayed.
line 39:
will set the visibility of
link_account
to the same value returned byanvil.users.get_user()
therefore if a user is logged in,
link_account
will be displayed, but if there is no user logged in, thenlink_account
will not be visible.
line 40:
will set the visibility of
link_logout
to the same value returned byanvil.users.get_user()
therefore if a user is logged in,
link_logout
will be displayed, but if there is no user logged in, thenlink_logout
will not be visible.
Before we test our code, we have one more issue we need to resolve. We need to redirect the user to Home, after they have finished with Login, Register and Logout. To do this, add the following highlighted code.
1 def link_register_click(self, **event_args):
2 anvil.users.signup_with_form(allow_cancel=True)
3 self.content_panel.clear()
4 self.content_panel.add_component(HomeComponent())
5 self.label_title.text = self.breadcrumb_stem
6 self.set_active_link("home")
7
8 def link_login_click(self, **event_args):
9 anvil.users.login_with_form(allow_cancel=True)
10 self.content_panel.clear()
11 self.content_panel.add_component(HomeComponent())
12 self.label_title.text = self.breadcrumb_stem
13 self.set_active_link("home")
14
15 def link_logout_click(self, **event_args):
16 anvil.users.logout()
17 self.content_panel.clear()
18 self.content_panel.add_component(HomeComponent())
19 self.label_title.text = self.breadcrumb_stem
20 self.set_active_link("home")
Code explaination
These have been copied from the link_home_click
method and are all the steps we need to do to load the HomeComponent.
Test¶
Before we test this code, go to the User table and delete all the rows (ie. all your users). Then launch your website.
Not Registered nor logged in¶
At first, since you now have no users, the user cannot possibly be logged in. You should see both the Register and the Login links.
Registered and logged in¶
Click Register and register a new user (you can reuse the ones you deleted if you want).
Now there is a user logged in, so you only see the Account and Logout links.
Logout¶
Now click the Logout button.
Since there is no user logged in you should see the Register and Login links.
Login¶
Finally click the Login button and use the user credentials you just registered.
Since there is a user logged in again, you should see the Account and Logout links.
If your website acts this way, then you have finished this tutorial
Final code state¶
By the end of this tutorial your code should be the same as below:
Final MainForm¶
1from ._anvil_designer import MainFormTemplate
2from anvil import *
3import anvil.tables as tables
4import anvil.tables.query as q
5from anvil.tables import app_tables
6import anvil.users
7from ..HomeComponent import HomeComponent
8from ..CalendarComponent import CalendarComponent
9from ..AddComponent import AddComponent
10from ..AccountComponent import AccountComponent
11
12
13class MainForm(MainFormTemplate):
14 def __init__(self, **properties):
15 # Set Form properties and Data Bindings.
16 self.init_components(**properties)
17 self.breadcrumb_stem = self.label_title.text
18
19 # Any code you write here will run before the form opens.
20 self.content_panel.add_component(HomeComponent())
21 self.set_active_link("home")
22
23 def set_active_link(self, state):
24 if state == "home":
25 self.link_home.role = "selected"
26 else:
27 self.link_home.role = None
28 if state == "add":
29 self.link_add.role = "selected"
30 else:
31 self.link_add.role = None
32 if state == "calendar":
33 self.link_calendar.role = "selected"
34 else:
35 self.link_calendar.role = None
36
37 self.link_register.visible = not anvil.users.get_user()
38 self.link_login.visible = not anvil.users.get_user()
39 self.link_account.visible = anvil.users.get_user()
40 self.link_logout.visible = anvil.users.get_user()
41
42 # --- link handlers
43 def link_home_click(self, **event_args):
44 self.content_panel.clear()
45 self.content_panel.add_component(HomeComponent())
46 self.label_title.text = self.breadcrumb_stem
47 self.set_active_link("home")
48
49 def link_calendar_click(self, **event_args):
50 self.content_panel.clear()
51 self.content_panel.add_component(CalendarComponent())
52 self.label_title.text = self.breadcrumb_stem + " - Calendar"
53 self.set_active_link("calendar")
54
55 def link_add_click(self, **event_args):
56 self.content_panel.clear()
57 self.content_panel.add_component(AddComponent())
58 self.label_title.text = self.breadcrumb_stem + " - Add"
59 self.set_active_link("add")
60
61 def link_account_click(self, **event_args):
62 """This method is called when the link is clicked"""
63 self.content_panel.clear()
64 self.content_panel.add_component(AccountComponent())
65 self.label_title.text = self.breadcrumb_stem + " - Account"
66 self.set_active_link(("account"))
67
68 def link_register_click(self, **event_args):
69 anvil.users.signup_with_form(allow_cancel=True)
70 self.content_panel.clear()
71 self.content_panel.add_component(HomeComponent())
72 self.label_title.text = self.breadcrumb_stem
73 self.set_active_link("home")
74
75 def link_login_click(self, **event_args):
76 anvil.users.login_with_form(allow_cancel=True)
77 self.content_panel.clear()
78 self.content_panel.add_component(HomeComponent())
79 self.label_title.text = self.breadcrumb_stem
80 self.set_active_link("home")
81
82 def link_logout_click(self, **event_args):
83 anvil.users.logout()
84 self.content_panel.clear()
85 self.content_panel.add_component(HomeComponent())
86 self.label_title.text = self.breadcrumb_stem
87 self.set_active_link("home")