Skip to content

observablehq/embedded-analytics-django-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Framework Embedded Analytics in Django

This repository is an example of importing a JS module from a Observable Cloud data app using signed URLs and embedding it in a Django. The Observable Cloud data app provides charts of the number of medals won by countries in the 2024 Olympic Games, optionally broken down by continent.

Tour

The repository uses Observable Cloud's signed URLs feature, which enables secure embedding for private data apps. In this example the data app is public, for demonstration purposes.

The entry point for embedding is in the index function in charts/views.py. It generates a signed URL containg a JWT generated with PyJWT. Then it renders a Jinja template including that URL to send to the browser:

def index(request):
    signed_url = sign_embedded_chart_url(f"{project_base_url}/medals-chart.js")
    context = {
        'medal_chart_url': signed_url,
    }
    return render(request, "charts/index.html", context)

def sign_embedded_chart_url(url):
    parsed_url = urlparse(url)

    nbf = datetime.datetime.now().timestamp()
    nbf -= (nbf % (SIGNATURE_ALIGN_MIN * 60))
    exp = nbf + (SIGNATURE_VALIDITY_MIN * 60)

    payload_data = {
        'sub': 'django-example',
        'urn:observablehq:path': parsed_url.path,
        'nbf': int(nbf),
        'exp': int(exp),
    }
    token = jwt.encode(payload_data, settings.EMBED_PRIVATE_KEY, algorithm='EdDSA')
    return f"{url}?token={token}"

The Jinja template at charts/templates/charts/index.html includes a JS script that imports the module from the signed URL, and then renders it into the page:

{% extends "./layout.html" %}

{% block content %}
  <h1>Olympic Medals</h1>
  <div id="medals-chart"></div>

  <script type="module">
    const {MedalsChart} = await import("{{ medal_chart_url }}");
    const target = document.querySelector("#medals-chart");
    target.append(await MedalsChart());
  </script>
{% endblock %}

Development

Create and activate virtual environment

python3 -m venv .venv
source .venv/bin/activate

Install dependencies

pip install -r requirements.txt

Run the server

python manage.py runserver

About

No description, website, or topics provided.

Resources

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published