Skip to content

Latest commit

 

History

History
260 lines (201 loc) · 6.81 KB

34a_get_chart_func.md

File metadata and controls

260 lines (201 loc) · 6.81 KB

Get Chart Function

- 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.

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.
: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.

  1. 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.

  1. 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

  1. Open the CalendarComponent in Code mode
  2. 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

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

: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

Final CalendarComponent

: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