Chapter 4:
Plot data from an external SQL database

We’ve seen how to construct the UI and plot data from an Anvil Data Table. Now let’s look at plotting data from data sources outside Anvil.

We’ll start with data from an external SQL database (PostgreSQL in this example.)

Step 1: Get the data

Let’s say one of our primary business concerns is user acquisition. But our user records live in an SQL database. We want to connect to this database, query it, and display this data in our dashboard.

We want to display data from our external database when our app is opened. Anvil apps are just Python, so we can use the standard Python tools to query our database!

In this case, our database is PostgreSQL, so we’ll use the Psycopg2 library.

Go to your Server Module, and add this line at the top:

import psycopg2

If you’re using the free plan, you’ll need to use psycopg2 from an Uplink script instead (here’s why).

Follow the next chapter to see how to make queries from an Uplink script, then come back here and follow this chapter using your Uplink script instead of a Server Module.

Now write a function in your Server Module to query the database, and return the results. Here’s an example query you might perform to track user acquisition, if your database has a users table with a signup_date field:

@anvil.server.callable
def get_user_signups():
  # Connect and retrieve data from your existing database - example code below
  conn = psycopg2.connect("host=db.myapp.com dbname=my_app user=postgres password=secret")
  cur = conn.cursor()
  cur.execute("""
     SELECT COUNT(${html`*`}), DATE_TRUNC('week', signup_date) AS d
          FROM users
          WHERE signup_date > NOW() - INTERVAL '3 months'
          GROUP BY DATE_TRUNC('week', signup_date)
          ORDER BY d;
  """)
  return list(cur)

For more information on using SQL databases with Anvil, click here.

If you don’t have a database available, you can use some dummy data instead. Remove the import psycopg2 statement, and add this function to your Server Module instead:

@anvil.server.callable
def get_user_signups():
# Here's some dummy data that you might return from your database, as an example
  return [{'signups': 120, 'date':datetime(2019, 6, 10, 0, 0)}, 
          {'signups': 180, 'date':datetime(2019, 6, 3, 0, 0)}, 
          {'signups': 150, 'date':datetime(2019, 5, 27, 0, 0)}]

We’re using the datetime library to create datetime objects, so you’ll also need to import the datetime class at the top of your Server Module:

from datetime import datetime

Step 2: Plot the data

All that’s left is to display this data in our dashboard. We’ll call the get_user_signups function from client code and put the data into a plot just as we did in Chapter 3.

Go to Form1’s ‘Code’ view and add this build_signups_graph function:

def build_signups_graph(self):
    # Get the data from our external database, and store it as 'signups'
    signups = anvil.server.call('get_user_signups')
    # Create a Scatter plot with this data, and change the colour of the line
    scatter = go.Scatter(x = [x['date'] for x in signups],
                         y = [x['signups'] for x in signups],
                         fill='tozeroy',
                         line=dict(color='#2196f3'))
    self.plot_2.data = scatter

We want to plot this data when our app runs, so let’s call it from the __init__ method of Form1:

self.build_signups_graph()

Run your app

Click run and your dashboard should look something like this:

Screenshot of dashboard with two graphs

That’s great, our app now displays data from an external data source as well as Anvil’s built-in database.

Next, we’ll plot data from a private database.

Chapter complete

Congratulations, you've completed this chapter!