Get Chart Function

The final frontend component that retrieves data from the backend is the CalendarComponent. In particular it retrieves the Gantt chart using the get_chart method.

Planning

Just like the previous data, we need to cache the diagram so that it only gets retrieved:

  • the first time CalendarComponent is called.

  • when the data in the Assessments table is updated.

This should be very familiar by now, so let’s get to the coding

Coding

First we need to create a variable in the data_access module to store the diagram.

  1. Open the data_access module

  2. Add the highlighted line to the bottom of the cached values section.

 7# cached values
 8__user = None
 9__assessments = None
10__chart = None

Code explaination

  • line 9 → creates the private variable __chart to store the diagram

Then we need to create a method that will cache and return the chart.

  1. At the bottom of the data_access module add the highlighted code

70def get_chart():
71  global __chart
72
73  if __chart:
74    print("Using cached chart")
75    return __chart
76
77  print("Building new chart from database")
78  __chart = anvil.server.call('get_chart', user, assessments)
79  return __chart

Code explaination

  • line 70 → creates the get_chart method

  • line 71 → allows the method to edit the value of __chart

  • line 73 → checks if the chart is already cached

  • line 74 → informs the developer that the cached chart is being used

  • line 75 → returns the cached chart and ends the method

  • line 77 → informs the developed that a new chart is being built

  • line 78 → builds a new chart and stores it in the __chart variable

  • line 79 → returned the cached chart

We also need to re-cache the chart when the assessments data is updated.

  1. Go to the my_assessment function and add the highlighted line of code

55def update_assessment(assessment_id, subject, details, start_date, due_date, completed):
56  global __assessments
57
58  print("Updating assessment details on the database")
59  anvil.server.call('update_assessment',
60                    assessment_id,
61                    subject,
62                    details,
63                    start_date,
64                    due_date,
65                    completed
66                   )
67  __assessments = None
68  __chart = None
69  my_assessment()

Code explaination

  • line 68 → reset __chart to None meaning the next time get_chart is called, a new chart will be built and cached.

Finally we need to replace the call to backend in CalendarComponent

  1. Open the CalendarComponent in Code mode

  2. Change the highlighted code in the load_chart method

26  def load_chart(self):
27    fig = data_access.get_chart()
28        
29    # Assign the Plotly figure to the Anvil Plot component
30    self.plot_timeline.figure = fig

Code explaination

line 27 → retrieves the cached chart

Testing

Launch your web site for testing.

  1. Navigate to the Calendar page (this should still load slowly)

  2. Navigate back to the Home page (this should be quick)

  3. Navigate back to the Calendar page (this should be quick now)

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__assessments = None
10__chart = None
11
12def the_user():
13  global __user
14
15  if __user:
16    print("Using cached user")
17    return __user
18
19  print("Accessing user from database")
20  __user = anvil.users.get_user()
21  return __user
22
23def logout():
24  global __user
25  __user = None
26  anvil.users.logout()
27
28def update_user(first_name, last_name):
29  global __user
30  
31  print("Writing user details to database")
32  anvil.server.call('update_user', first_name, last_name)
33  __user = None
34  __user = the_user()
35
36def my_assessment():
37  global __assessments
38  
39  if __assessments:
40    print("Using cached assessments")
41    return __assessments
42
43  print("Accessing assessments from database")
44  __assessments = anvil.server.call('get_assessment')
45  return __assessments
46
47def add_assessment(subject, details, start_date, due_date):
48  global __assessments
49  
50  print("Writing assessment details to the database")
51  anvil.server.call('add_assessment', subject, details, start_date, due_date)
52  __assessments = None
53  my_assessment()
54
55def update_assessment(assessment_id, subject, details, start_date, due_date, completed):
56  global __assessments
57
58  print("Updating assessment details on the database")
59  anvil.server.call('update_assessment',
60                    assessment_id,
61                    subject,
62                    details,
63                    start_date,
64                    due_date,
65                    completed
66                   )
67  __assessments = None
68  __chart = None
69  my_assessment()
70
71def get_chart():
72  global __chart
73
74  if __chart:
75    print("Using cached chart")
76    return __chart
77
78  print("Building new chart from database")
79  __chart = anvil.server.call('get_chart')
80  return __chart

Final CalendarComponent

 1from ._anvil_designer import CalendarComponentTemplate
 2from anvil import *
 3import plotly.graph_objects as go
 4import anvil.server
 5import anvil.tables as tables
 6import anvil.tables.query as q
 7from anvil.tables import app_tables
 8import anvil.users
 9from .. import data_access
10
11
12class CalendarComponent(CalendarComponentTemplate):
13  def __init__(self, **properties):
14    # Set Form properties and Data Bindings.
15    self.init_components(**properties)
16
17    # Any code you write here will run before the form opens.
18    if data_access.the_user():
19      self.card_details.visible = True
20      self.card_error.visible = False
21      self.load_chart()
22    else:
23      self.card_details.visible = False
24      self.card_error.visible = True
25
26  def load_chart(self):
27    fig = data_access.get_chart()
28        
29    # Assign the Plotly figure to the Anvil Plot component
30    self.plot_timeline.figure = fig