DjangoにPlotlyのグラフを表示する

5 min read読了の目安(約4600字

背景

データを扱ったWebアプリケーションでは、そのデータを可視化してダッシュボードのように表示したい場合があると思います。 Dash を利用することでインタラクティブにデータを可視化できるWebアプリケーションを容易に構築できます。

Dashについては共著 Python インタラクティブ・データビジュアライゼーション入門 ―Plotly/Dashによるデータ可視化とWebアプリ構築― にて詳しく解説しています。ご興味があるかたぜひお手にとって見てください。

Dashは予めデータが用意されている場合には便利なフレームワークですが、ユーザがデータを入力するケースなどにおいてはDjangoのようなモデルが用意されているフレームワークを検討してもよいかもしれません。

ようやく本題となりますが、DjangoのWebアプリケーションのデータの可視化部分を plotly.py で実装してみます。
plotly.pyを利用する利点としては次のようなものが挙げられます。

  • インタラクティブな可視化が実装できる
  • さまざまな分野に対応した多数のグラフライブラリが用意されている
  • HTML形式に出力できるため、テンプレートにすばやく組み込める

実装手順

今回は可視化部分の実装方法を理解しやすくするため、必要最低限の構成にします。

Python3.6以降の仮想環境を用意し、必要なライブラリをインストールします。

pip install plotly django

プロジェクトとアプリケーションを作成します。

django-admin startproject mysite
cd mysite
python manage.py startapp app

次のようなディレクトリ構成になります。

tree
.
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── mysite
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-38.pyc
    │   └── settings.cpython-38.pyc
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

mysite/settings.py に作成したアプリケーションとテンプレートのディレクトリを登録します(#追記の行)。

mysite/settings.py
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',  # 追記
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],  # 追記
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

URLディスパッチャを追加します。今回はルート(/)にグラフが描画されるだけのWebアプリケーションにします。

mysite/ulrs.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import RedirectView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',  include(('app.urls', 'app'), namespace='app', )),
]
app/urls.py
from django.urls import path

from . import views

urlpatterns = [path("", views.LineChartsView.as_view(), name="plot")]

ビューを作成します。ここが今回のポイントです。plotly.pyで描画したデータをHTMLに出力してテンプレートに渡します。今回は TemplateView を利用します(❶)。

plotly.pyには figure と呼ばれる描画領域を管理するオブジェクトがあり、このオブジェクトからHTML上にグラフを描画したり、Jupyter上にグラフを描画できます。今回は紹介していませんが、 Plotly Express についても同様です。

度々の宣伝ですが、plotly.py(Plotly Express)ついても共著 Python インタラクティブ・データビジュアライゼーション入門 ―Plotly/Dashによるデータ可視化とWebアプリ構築― にて詳しく解説しています。

figure オブジェクトをHTMLに出力するには to_html メソッドを実行します(❷)。plotly.pyは plotly.js が元になったラッパーで、HTMLにはJavaScriptが含まれますが、後述するCDNを利用するため、引数 include_plotlyjsFalse にしてJavaScript部分以外を出力します。

plotly.pyのグラフがHTML化できたので、これを TemplateView に追加します(❸)。

app/views.py
from django.views.generic import TemplateView  # ❶
import plotly.graph_objects as go


def line_charts():
    fig = go.Figure(
        go.Scatter(x=[1, 2, 3], y=[3, 5, 2]), layout=go.Layout(width=400, height=400)
    )
    return fig.to_html(include_plotlyjs=False)  # ❷


class LineChartsView(TemplateView):  # ❶
    template_name = "plot.html"

    def get_context_data(self, **kwargs):
        context = super(LineChartsView, self).get_context_data(**kwargs)
        context["plot"] = line_charts()  # ❸
        return context

上記で出力したHTMLをテンプレートに組込みます。ヘッダにはplotly.jsのCDNを参照し、上記のビューで生成したHTMLを渡します。

templates/plot.html
{% block head %}
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
{% endblock %}

{% block content %}
<div class="title"><h1>Plotlyのグラフを描画</h1></div>
<div class="graph">{{plot|safe}}</div>
{% endblock %}

マイグレーション

一通りのファイルが準備できたらマイグレーションして終了です。

python manage.py makemigrations
python manage.py migrate

動作確認

Webサーバを起動すると、ブラウザ上には下記のように表示されます。

python manage.py runserver

サンプルプロジェクト

本記事のソースコードを次のリポジトリに用意しました。

https://github.com/drillan/plotly-django-sample