- Understand how to cache data for efficient retrieval.
- Create a private variable to store the chart.
- Implement a method to check if the chart is cached and retrieve it if available, or regenerate it if not.
- Modify the **CalendarComponent** to utilize the cached chart.
- Test the implementation to ensure efficiency.
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.
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
First we need to create a variable in the data_access module to store the diagram.
- Open the data_access module
- Add the highlighted line to the bottom of the cached values section.
:linenos:
:lineno-start: 7
:emphasize-lines: 4
# cached values
__user = None
__assessments = None
__chart = None
:class: notice
- **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.
- At the bottom of the data_access module add the highlighted code
:linenos:
:lineno-start: 70
:emphasize-lines: 1 - 10
def get_chart():
global __chart
if __chart:
print("Using cached chart")
return __chart
print("Building new chart from database")
__chart = anvil.server.call('get_chart', user, assessments)
return __chart
:class: notice
- **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.
- Go to the my_assessment function and add the highlighted line of code
:linenos:
:lineno-start: 55
:emphasize-lines: 14
def update_assessment(assessment_id, subject, details, start_date, due_date, completed):
global __assessments
print("Updating assessment details on the database")
anvil.server.call('update_assessment',
assessment_id,
subject,
details,
start_date,
due_date,
completed
)
__assessments = None
__chart = None
my_assessment()
:class: notice
- **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
- Open the CalendarComponent in Code mode
- Change the highlighted code in the load_chart method
:linenos:
:lineno-start: 26
:emphasize-lines: 2
def load_chart(self):
fig = data_access.get_chart()
# Assign the Plotly figure to the Anvil Plot component
self.plot_timeline.figure = fig
:class: notice
**line 27** → retrieves the cached chart
Launch your web site for testing.
- Navigate to the Calendar page (this should still load slowly)
- Navigate back to the Home page (this should be quick)
- Navigate back to the Calendar page (this should be quick now)
By the end of this tutorial your code should be the same as below:
:linenos:
import anvil.server
import anvil.users
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
# cached values
__user = None
__assessments = None
__chart = None
def the_user():
global __user
if __user:
print("Using cached user")
return __user
print("Accessing user from database")
__user = anvil.users.get_user()
return __user
def logout():
global __user
__user = None
anvil.users.logout()
def update_user(first_name, last_name):
global __user
print("Writing user details to database")
anvil.server.call('update_user', first_name, last_name)
__user = None
__user = the_user()
def my_assessment():
global __assessments
if __assessments:
print("Using cached assessments")
return __assessments
print("Accessing assessments from database")
__assessments = anvil.server.call('get_assessment')
return __assessments
def add_assessment(subject, details, start_date, due_date):
global __assessments
print("Writing assessment details to the database")
anvil.server.call('add_assessment', subject, details, start_date, due_date)
__assessments = None
my_assessment()
def update_assessment(assessment_id, subject, details, start_date, due_date, completed):
global __assessments
print("Updating assessment details on the database")
anvil.server.call('update_assessment',
assessment_id,
subject,
details,
start_date,
due_date,
completed
)
__assessments = None
__chart = None
my_assessment()
def get_chart():
global __chart
if __chart:
print("Using cached chart")
return __chart
print("Building new chart from database")
__chart = anvil.server.call('get_chart')
return __chart
:linenos:
from ._anvil_designer import CalendarComponentTemplate
from anvil import *
import plotly.graph_objects as go
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
from .. import data_access
class CalendarComponent(CalendarComponentTemplate):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run before the form opens.
if data_access.the_user():
self.card_details.visible = True
self.card_error.visible = False
self.load_chart()
else:
self.card_details.visible = False
self.card_error.visible = True
def load_chart(self):
fig = data_access.get_chart()
# Assign the Plotly figure to the Anvil Plot component
self.plot_timeline.figure = fig