Create Logout Function

In testing your website in the last tutorial, you would have noticed that when you logout, the website is still acting like your are logged in. This is a problem.

Planning

Although the website looks like it remains logged in, it is actually logged out. For example, interacting with the database through changing user details would produce an error. The reason for this discrepancy, is that the website continues to use the cached user after the user has logged out.

To resolve this issue we need the MainForm link_logout_click handler to:

  1. call the anvil.users.logout() method

  2. clear the cached user value

We will create a new function in the data_access module to do this.

Code

First we need to make the new method in the data_access module.

  1. Open the data_access module

  2. Add the following code to the bottom of the module

21def logout():
22  global __user
23  __user = None
24  anvil.users.logout()

Code explaination

  • line 21 → creates the logout function

  • line 22 → allows the function to edit the value of __user

  • line 23 → sets __user to None

  • line 24 → logs out the current user

Now we need to change the link_logout_click handler so it calls this function.

  1. Open the MainForm in Code mode

  2. Change line 95 to the highlighted code below

94  def link_logout_click(self, **event_args):
95    data_access.logout()
96    self.switch_component("home")

Code explaination

  • line 95 → calls the logout function we just made

Testing

Time to check if that worked.

Launch your website and then logout. You should be taken to the Welcome page.

Final code state

By the end of this tutorial your code should be the same as below:

Final data_access

 1import anvil.server
 2import anvil.users
 3import anvil.tables as tables
 4import anvil.tables.query as q
 5from anvil.tables import app_tables
 6
 7# cached values
 8__user = None
 9
10def the_user():
11  global __user
12
13  if __user:
14    print("Using cached user")
15    return __user
16
17  print("Accessing user from database")
18  __user = anvil.users.get_user()
19  return __user
20
21def logout():
22  global __user
23  __user = None
24  anvil.users.logout()

Final MainForm

 1from ._anvil_designer import MainFormTemplate
 2from anvil import *
 3import anvil.server
 4import anvil.tables as tables
 5import anvil.tables.query as q
 6from anvil.tables import app_tables
 7import anvil.users
 8from ..HomeComponent import HomeComponent
 9from ..CalendarComponent import CalendarComponent
10from ..AddComponent import AddComponent
11from ..AccountComponent import AccountComponent
12from ..SetDetailsComponent import SetDetailsComponent
13from ..WelcomeComponent import WelcomeComponent
14from .. import data_access
15
16
17class MainForm(MainFormTemplate):
18  def __init__(self, **properties):
19    # Set Form properties and Data Bindings.
20    self.init_components(**properties)
21    self.breadcrumb_stem = self.label_title.text
22
23    # Any code you write here will run before the form opens.
24    self.switch_component("home")
25
26  def switch_component(self, state):
27    # set state
28    if state == "home":
29      if data_access.the_user():
30        cmpt = HomeComponent()
31      else:
32        cmpt = WelcomeComponent()
33      breadcrumb = self.breadcrumb_stem
34    elif state == "account":
35      cmpt = AccountComponent()
36      breadcrumb = self.breadcrumb_stem + " - Account"
37    elif state == "add":
38      cmpt = AddComponent()
39      breadcrumb = self.breadcrumb_stem + " - Add"
40    elif state == "calendar":
41      cmpt = CalendarComponent()
42      breadcrumb = self.breadcrumb_stem + " - Calendar"
43    elif state == "details":
44      cmpt = SetDetailsComponent()
45      breadcrumb = self.breadcrumb_stem + " - Account - Set Details"
46    
47    # execution
48    self.content_panel.clear()
49    self.content_panel.add_component(cmpt)
50    self.label_title.text = breadcrumb
51    self.set_active_link(state)
52  
53  def set_active_link(self, state):
54    if state == "home":
55      self.link_home.role = "selected"
56    else:
57      self.link_home.role = None
58    if state == "add":
59      self.link_add.role = "selected"
60    else:
61      self.link_add.role = None
62    if state == "calendar":
63      self.link_calendar.role = "selected"
64    else:
65      self.link_calendar.role = None
66
67    self.link_register.visible = not data_access.the_user()
68    self.link_login.visible = not data_access.the_user()
69    self.link_account.visible = data_access.the_user()
70    self.link_logout.visible = data_access.the_user()
71  
72  # --- link handlers
73  def link_home_click(self, **event_args):
74    self.switch_component("home")
75
76  def link_calendar_click(self, **event_args):
77    self.switch_component("calendar")
78
79  def link_add_click(self, **event_args):
80    self.switch_component("add")
81
82  def link_account_click(self, **event_args):
83    """This method is called when the link is clicked"""
84    self.switch_component("account")
85
86  def link_register_click(self, **event_args):
87    anvil.users.signup_with_form(allow_cancel=True)
88    self.switch_component("details")
89
90  def link_login_click(self, **event_args):
91    anvil.users.login_with_form(allow_cancel=True)
92    self.switch_component("home")
93
94  def link_logout_click(self, **event_args):
95    data_access.logout()
96    self.switch_component("home")