前回、Dashを利用して世界統計地図を描いてみましたが、これだとシングルページなんですよね。
Dash自体はマルチページにも対応してしてます。が、今後、Webアプリケーションとして機能を拡張していくことを考えたら、DjangoでDashを利用できると良いですよね。
いろいろ調べたところ、django-plotly-dashというパッケージが良さそうということで、試してみました。一部、苦労しましたが、うまくいきましたので、紹介します。
django-plotly-dash — django-plotly-dash documentation
前回Dashにて描いた世界地図をDjangoに統合する例を説明していきます。
環境
- python==3.7.7
- Django== 3.0.8
- dash==1.11.0
- dash-bootstrap-components==0.10.3
- django-bootstrap4==2.2.0
以下は、世界銀行データからグラフを作成するのに使います。 - pandas==1.0.5
- world-bank-data==0.1.3
まずはDjangoのプロジェクト・アプリを設定しておく
django-admin startproject djangomap
任意のプロジェクト名(ここではdjangomap)にてDjangoプロジェクトを設定します。
このプロジェクト名のフォルダができるので、そのフォルダ下に移動し、アプリケーションを作成します。
ここではworldmapというアプリケーション名にしています。
python manage.py startapp worldmap
Django-plotly-dashをインストールする
pip install django_plotly_dash
ドキュメンテーションに従って、以下もインストールしておきます。
pip install channels daphne redis django-redis channels-redis
さらに以下もインストールします。
pip install dpd-components dpd-static-support
settings.pyの設定
settings.pyを変更していきます。まずは、インストールしたアプリケーションを利用できるように設定します。
# djangomap/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_plotly_dash.apps.DjangoPlotlyDashConfig', # django-plotly-dashにより追加 'channels', # django_plotly_dashとともにchannelsをインストールしたため追加 'channels_redis', # django_plotly_dashとともにchannels_redisをインストールしたため追加 'bootstrap4', #django-bootstrap4を利用する場合 'worldmap.apps.WorldmapConfig' # 通常のdjangoアプリ設定に伴う追加 ]
続いて、以下を丸々、settings.pyの最後に追加します。
### django_plotly_dashにて追加(ここから) ### ASGI_APPLICATION = 'djangomap.routing.application' # djangomapのところにはプロジェクト名が入ります。 CHANNEL_LAYERS = { 'default':{ 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { 'hosts':[('127.0.0.1', 6379),], } } } STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'django_plotly_dash.finders.DashAssetFinder', 'django_plotly_dash.finders.DashComponentFinder' ] PLOTLY_COMPONENTS = [ 'dash_core_components', 'dash_html_components', 'dash_renderer', 'dpd_components', 'dpd_static_support', 'dash_bootstrap_components', ] X_FRAME_OPTIONS = 'SAMEORIGIN' ### django_plotly_dashにて追加(ここまで) ###
urls.pyを修正(プロジェクトレベル)
プレジェクトレベル(ここではdjangomapフォルダ直下)の`urls.py'に以下を追加する。
urlpatterns = [
path('', include('worldmap.urls')),
path('admin/', admin.site.urls),
path('django_plotly_dash/', include('django_plotly_dash.urls')), # これを追加
]
routing.pyを追加
プロジェクトフォルダ直下にrouting.pyを追加します。
routing.pyには以下を記述します。
from channels.routing import ProtocolTypeRouter application = ProtocolTypeRouter({ })
Dashアプリの変更
前回作ったDashアプリを修正していきます。アプリケーションレベル(ここではworldmapフォルダ直下)に、dashアプリ
- import dashをfrom django_plotly_dash import DjangoDashに変更する
- dash.Dash(...)をDjangoDash('WorldMap', add_bootstrap_links=True)に変更する
- if name == "main":
app.run_server() を削除する
Dashアプリを表示するhtmlファイルを作成
アプリケーションレベル(ここではwouldmap直下)にtemplatesフォルダを作成、さらにworldmapフォルダを作成(Djangoの慣習)。そこに例えば、index.htmlを作成する(名前は任意)。そのファイルには以下の通り、記述する。
{% extends 'base.html' %}
{% block content %}
{% load plotly_dash %}
<div class="{% plotly_class name='WorldMap' %} card" style="height: 100%; width: 100%;">
{% plotly_app name='WorldMap' ratio=1.0 %}
</div>
{% endblock %}
順番が前後してしまいましたが、プロジェクトと同レベルにtemplatesフォルダを作成し、その中にbase.htmlを作成します。
そのbase.htmlには、ここではサンプルとして、Bootstrap4.3の以下のページの最初に出てくるNavbarをコピペして利用します。
views.pyとurls.py(アプリケーションレベル)
アプリケーションレベル(ここではworldmap)のviews.pyは通常通り。
# views.py from django.shortcuts import render def index(request): return render(request, 'worldmap/index.html')
urls.pyでは、Dashアプリをインポートしておく必要があります。
# urls.py from django.urls import path from . import views from . import worldmap # これが必要 app_name = 'worldmap' urlpatterns = [ path('', views.index, name='index') ]
これで設定できました。さて、migrateを忘れるとうまく動きません。
python manage.py migrate
を忘れずに。そして、以下で起動してみると。
python manage.py runserver

うまく行きました!
↓スクリプトはこちらにアップしておきました。
番外編
なお、上記の簡単な例をベースに、より機能強化を図ったサイトを作成し、Herokuにデプロイしましたので、こちらにもよろしければどうぞ。