From abc9abfe7ea4868e1be4b1a5df47041e8045d233 Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Wed, 26 Dec 2018 16:10:45 -0800 Subject: [PATCH 01/10] v0.9.5 packages for future reference --- frozen_dev.txt | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/frozen_dev.txt b/frozen_dev.txt index f6eb025d..eb773fd1 100644 --- a/frozen_dev.txt +++ b/frozen_dev.txt @@ -6,31 +6,35 @@ astroid==2.0.4 async-timeout==2.0.1 atomicwrites==1.2.1 attrs==18.2.0 -autobahn==18.8.2 +autobahn==18.9.2 Automat==0.7.0 Babel==2.6.0 +bleach==3.0.2 certifi==2018.8.24 +cffi==1.11.5 channels==2.1.3 channels-redis==2.3.0 chardet==3.0.4 -click==6.7 +Click==7.0 +cmarkgfm==0.4.2 constantly==15.1.0 coverage==4.5.1 daphne==2.2.2 -dash==0.28.5 -dash-core-components==0.28.1 -dash-html-components==0.11.0 -dash-renderer==0.13.2 +dash==0.28.2 +dash-core-components==0.33.0 +dash-html-components==0.13.2 +dash-renderer==0.14.3 decorator==4.3.0 -Django==2.1.1 +Django==2.1.2 django-bootstrap4==0.0.7 --e git+https://github.com/delsim/django-plotly-dash.git@1a6a184eac871a0a675fa971fe4c10c3dac195d8#egg=django_plotly_dash +-e git+https://github.com/delsim/django-plotly-dash.git@affccd8b280b2fdbc7f7e2d975b9cf4c7ace5f06#egg=django_plotly_dash django-redis==4.9.0 docopt==0.6.2 docutils==0.14 dpd-components==0.1.0 Flask==1.0.2 Flask-Compress==1.4.0 +future==0.16.0 grip==4.5.2 hiredis==0.2.0 hyperlink==18.0.0 @@ -45,13 +49,13 @@ jsonschema==2.6.0 jupyter-core==4.4.0 lazy-object-proxy==1.3.1 livereload==2.5.2 -Markdown==2.6.11 +Markdown==3.0.1 MarkupSafe==1.0 mccabe==0.6.1 more-itertools==4.3.0 msgpack==0.5.6 nbformat==4.4.0 -numpy==1.15.1 +numpy==1.15.2 packaging==18.0 pandas==0.23.4 path-and-address==2.0.1 @@ -59,20 +63,22 @@ pathlib2==2.3.2 pathtools==0.1.2 pkg-resources==0.0.0 pkginfo==1.4.2 -plotly==3.1.1 +plotly==3.3.0 pluggy==0.7.1 port-for==0.3.1 -py==1.6.0 +py==1.7.0 +pycparser==2.19 Pygments==2.2.0 PyHamcrest==1.9.0 pylint==2.1.1 -pyparsing==2.3.0 -pytest==3.7.4 -pytest-cov==2.5.1 -pytest-django==3.4.2 +pyparsing==2.2.2 +pytest==3.8.2 +pytest-cov==2.6.0 +pytest-django==3.4.3 python-dateutil==2.7.3 pytz==2018.5 PyYAML==3.13 +readme-renderer==22.0 redis==2.10.6 requests==2.19.1 requests-toolbelt==0.8.0 @@ -83,15 +89,16 @@ Sphinx==1.8.1 sphinx-autobuild==0.7.1 sphinx-rtd-theme==0.4.2 sphinxcontrib-websupport==1.1.0 -tornado==5.1 -tqdm==4.25.0 +tornado==5.1.1 +tqdm==4.26.0 traitlets==4.3.2 -twine==1.11.0 +twine==1.12.1 Twisted==18.7.0 txaio==18.8.1 typed-ast==1.1.0 urllib3==1.23 watchdog==0.9.0 +webencodings==0.5.1 Werkzeug==0.14.1 wrapt==1.10.11 zope.interface==4.5.0 From d15e282bf3bc05965d74ecc79d8c0d2094df02b4 Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sun, 6 Jan 2019 16:51:12 -0800 Subject: [PATCH 02/10] Rough-in of Django session state example --- demo/demo/templates/base.html | 2 ++ demo/demo/templates/demo_eight.html | 27 +++++++++++++++++++++++++++ demo/demo/templates/index.html | 1 + demo/demo/urls.py | 1 + 4 files changed, 31 insertions(+) create mode 100644 demo/demo/templates/demo_eight.html diff --git a/demo/demo/templates/base.html b/demo/demo/templates/base.html index 9d7eafda..740aed37 100644 --- a/demo/demo/templates/base.html +++ b/demo/demo/templates/base.html @@ -30,6 +30,8 @@ Four - Live Updating Five - Direct Injection Six - Simple Injection + Seven - Boostrap Components + Eight - Session State {% endif %} {% endblock %} Django Session State +

+ This example demonstrates passing session state values from Django to a Dash app. +

+
+
+

{% load plotly_dash %}

+

<div class="{% plotly_class name="BootstrapApplication"%}"> +

{% plotly_app name="BootstrapApplication" %}

+

<\div> +

+
+

+
+
+
+ {%plotly_app name="BootstrapApplication"%} +
+
+
+{%endblock%} diff --git a/demo/demo/templates/index.html b/demo/demo/templates/index.html index 7f419473..d6e727ad 100644 --- a/demo/demo/templates/index.html +++ b/demo/demo/templates/index.html @@ -14,5 +14,6 @@

Demonstration Application

  • Demo Five - injection of a Dash application without embedding in an html iframe
  • Demo Six - simple html injection example
  • Demo Seven - dash-bootstrap-components example
  • +
  • Demo Eight - Django session state example
  • {%endblock%} diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 75d148a3..832a46fb 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -43,6 +43,7 @@ url('^demo-five$', TemplateView.as_view(template_name='demo_five.html'), name="demo-five"), url('^demo-six', dash_example_1_view, name="demo-six"), url('^demo-seven', TemplateView.as_view(template_name='demo_seven.html'), name="demo-seven"), + url('^demo-eight', TemplateView.as_view(template_name='demo_eight.html'), name="demo-eight"), url('^admin/', admin.site.urls), url('^django_plotly_dash/', include('django_plotly_dash.urls')), From 9f02e1d45acbc636cdf0fbb6ba529d8104294b5f Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sat, 12 Jan 2019 23:39:23 -0800 Subject: [PATCH 03/10] Adapt boostrap demo --- demo/demo/bootstrap_app.py | 10 ++++++++++ demo/demo/templates/demo_eight.html | 11 +++++++---- demo/demo/urls.py | 4 ++-- demo/demo/views.py | 16 ++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/demo/demo/bootstrap_app.py b/demo/demo/bootstrap_app.py index cfa180af..9f028745 100644 --- a/demo/demo/bootstrap_app.py +++ b/demo/demo/bootstrap_app.py @@ -38,3 +38,13 @@ ] ) +dis = DjangoDash("DjangoSessionState", + add_bootstrap_links=True) + +dis.layout = html.Div( + [ + dbc.Alert("This is an alert", color="primary"), + dbc.Alert("Danger", color="danger"), + ] + ) + diff --git a/demo/demo/templates/demo_eight.html b/demo/demo/templates/demo_eight.html index 60a48396..1f7c4d18 100644 --- a/demo/demo/templates/demo_eight.html +++ b/demo/demo/templates/demo_eight.html @@ -8,19 +8,22 @@

    Django Session State

    This example demonstrates passing session state values from Django to a Dash app.

    +

    + The current value of ind_use is {{ind_use}} +

    {% load plotly_dash %}

    -

    <div class="{% plotly_class name="BootstrapApplication"%}"> -

    {% plotly_app name="BootstrapApplication" %}

    +

    <div class="{% plotly_class name="DjangoSessionState"%}"> +

    {% plotly_app name="DjangoSessionState" ratio=0.3 %}

    <\div>

    -
    - {%plotly_app name="BootstrapApplication"%} +
    + {%plotly_app name="DjangoSessionState" ratio=0.3 %}
    diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 832a46fb..0db3cf9e 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -32,7 +32,7 @@ from django_plotly_dash.views import add_to_session -from .views import dash_example_1_view +from .views import dash_example_1_view, session_state_view urlpatterns = [ url('^$', TemplateView.as_view(template_name='index.html'), name="home"), @@ -43,7 +43,7 @@ url('^demo-five$', TemplateView.as_view(template_name='demo_five.html'), name="demo-five"), url('^demo-six', dash_example_1_view, name="demo-six"), url('^demo-seven', TemplateView.as_view(template_name='demo_seven.html'), name="demo-seven"), - url('^demo-eight', TemplateView.as_view(template_name='demo_eight.html'), name="demo-eight"), + url('^demo-eight', session_state_view, {'template_name':'demo_eight.html'}, name="demo-eight"), url('^admin/', admin.site.urls), url('^django_plotly_dash/', include('django_plotly_dash.urls')), diff --git a/demo/demo/views.py b/demo/demo/views.py index b73a2f1f..bbaf782d 100644 --- a/demo/demo/views.py +++ b/demo/demo/views.py @@ -17,3 +17,19 @@ def dash_example_1_view(request, template_name="demo_six.html", **kwargs): request.session['django_plotly_dash'] = dash_context return render(request, template_name=template_name, context=context) + +def session_state_view(request, template_name, **kwargs): + + session = request.session + + demo_count = session.get('demo_eight_values', {}) + + ind_use = demo_count.get('ind_use', 0) + ind_use += 1 + demo_count['ind_use'] = ind_use + + context = {'ind_use' : ind_use} + + session['demo_eight_values'] = demo_count + + return render(request, template_name=template_name, context=context) From 87ce75b278a55445f2df1203891894d2c1229ebf Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sun, 6 Jan 2019 16:51:12 -0800 Subject: [PATCH 04/10] Rough-in of Django session state example --- demo/demo/templates/base.html | 2 ++ demo/demo/templates/demo_eight.html | 27 +++++++++++++++++++++++++++ demo/demo/templates/index.html | 1 + demo/demo/urls.py | 1 + 4 files changed, 31 insertions(+) create mode 100644 demo/demo/templates/demo_eight.html diff --git a/demo/demo/templates/base.html b/demo/demo/templates/base.html index 9d7eafda..740aed37 100644 --- a/demo/demo/templates/base.html +++ b/demo/demo/templates/base.html @@ -30,6 +30,8 @@ Four - Live Updating Five - Direct Injection Six - Simple Injection + Seven - Boostrap Components + Eight - Session State {% endif %} {% endblock %} Django Session State +

    + This example demonstrates passing session state values from Django to a Dash app. +

    +
    +
    +

    {% load plotly_dash %}

    +

    <div class="{% plotly_class name="BootstrapApplication"%}"> +

    {% plotly_app name="BootstrapApplication" %}

    +

    <\div> +

    +
    +

    +
    +
    +
    + {%plotly_app name="BootstrapApplication"%} +
    +
    +
    +{%endblock%} diff --git a/demo/demo/templates/index.html b/demo/demo/templates/index.html index 7f419473..d6e727ad 100644 --- a/demo/demo/templates/index.html +++ b/demo/demo/templates/index.html @@ -14,5 +14,6 @@

    Demonstration Application

  • Demo Five - injection of a Dash application without embedding in an html iframe
  • Demo Six - simple html injection example
  • Demo Seven - dash-bootstrap-components example
  • +
  • Demo Eight - Django session state example
  • {%endblock%} diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 75d148a3..832a46fb 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -43,6 +43,7 @@ url('^demo-five$', TemplateView.as_view(template_name='demo_five.html'), name="demo-five"), url('^demo-six', dash_example_1_view, name="demo-six"), url('^demo-seven', TemplateView.as_view(template_name='demo_seven.html'), name="demo-seven"), + url('^demo-eight', TemplateView.as_view(template_name='demo_eight.html'), name="demo-eight"), url('^admin/', admin.site.urls), url('^django_plotly_dash/', include('django_plotly_dash.urls')), From 19961b333575cfbacae82f1cfe23c0f822469370 Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sat, 12 Jan 2019 23:39:23 -0800 Subject: [PATCH 05/10] Adapt boostrap demo --- demo/demo/bootstrap_app.py | 10 ++++++++++ demo/demo/templates/demo_eight.html | 11 +++++++---- demo/demo/urls.py | 4 ++-- demo/demo/views.py | 16 ++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/demo/demo/bootstrap_app.py b/demo/demo/bootstrap_app.py index cfa180af..9f028745 100644 --- a/demo/demo/bootstrap_app.py +++ b/demo/demo/bootstrap_app.py @@ -38,3 +38,13 @@ ] ) +dis = DjangoDash("DjangoSessionState", + add_bootstrap_links=True) + +dis.layout = html.Div( + [ + dbc.Alert("This is an alert", color="primary"), + dbc.Alert("Danger", color="danger"), + ] + ) + diff --git a/demo/demo/templates/demo_eight.html b/demo/demo/templates/demo_eight.html index 60a48396..1f7c4d18 100644 --- a/demo/demo/templates/demo_eight.html +++ b/demo/demo/templates/demo_eight.html @@ -8,19 +8,22 @@

    Django Session State

    This example demonstrates passing session state values from Django to a Dash app.

    +

    + The current value of ind_use is {{ind_use}} +

    {% load plotly_dash %}

    -

    <div class="{% plotly_class name="BootstrapApplication"%}"> -

    {% plotly_app name="BootstrapApplication" %}

    +

    <div class="{% plotly_class name="DjangoSessionState"%}"> +

    {% plotly_app name="DjangoSessionState" ratio=0.3 %}

    <\div>

    -
    - {%plotly_app name="BootstrapApplication"%} +
    + {%plotly_app name="DjangoSessionState" ratio=0.3 %}
    diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 832a46fb..0db3cf9e 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -32,7 +32,7 @@ from django_plotly_dash.views import add_to_session -from .views import dash_example_1_view +from .views import dash_example_1_view, session_state_view urlpatterns = [ url('^$', TemplateView.as_view(template_name='index.html'), name="home"), @@ -43,7 +43,7 @@ url('^demo-five$', TemplateView.as_view(template_name='demo_five.html'), name="demo-five"), url('^demo-six', dash_example_1_view, name="demo-six"), url('^demo-seven', TemplateView.as_view(template_name='demo_seven.html'), name="demo-seven"), - url('^demo-eight', TemplateView.as_view(template_name='demo_eight.html'), name="demo-eight"), + url('^demo-eight', session_state_view, {'template_name':'demo_eight.html'}, name="demo-eight"), url('^admin/', admin.site.urls), url('^django_plotly_dash/', include('django_plotly_dash.urls')), diff --git a/demo/demo/views.py b/demo/demo/views.py index b73a2f1f..bbaf782d 100644 --- a/demo/demo/views.py +++ b/demo/demo/views.py @@ -17,3 +17,19 @@ def dash_example_1_view(request, template_name="demo_six.html", **kwargs): request.session['django_plotly_dash'] = dash_context return render(request, template_name=template_name, context=context) + +def session_state_view(request, template_name, **kwargs): + + session = request.session + + demo_count = session.get('demo_eight_values', {}) + + ind_use = demo_count.get('ind_use', 0) + ind_use += 1 + demo_count['ind_use'] = ind_use + + context = {'ind_use' : ind_use} + + session['demo_eight_values'] = demo_count + + return render(request, template_name=template_name, context=context) From 20928a9fa63f13d0e65f9a742d0e26375d8987bb Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sun, 6 Jan 2019 16:51:12 -0800 Subject: [PATCH 06/10] Rough-in of Django session state example --- demo/demo/templates/base.html | 2 ++ demo/demo/templates/demo_eight.html | 27 +++++++++++++++++++++++++++ demo/demo/templates/index.html | 1 + demo/demo/urls.py | 1 + 4 files changed, 31 insertions(+) create mode 100644 demo/demo/templates/demo_eight.html diff --git a/demo/demo/templates/base.html b/demo/demo/templates/base.html index 9d7eafda..740aed37 100644 --- a/demo/demo/templates/base.html +++ b/demo/demo/templates/base.html @@ -30,6 +30,8 @@ Four - Live Updating Five - Direct Injection Six - Simple Injection + Seven - Boostrap Components + Eight - Session State {% endif %} {% endblock %} Django Session State +

    + This example demonstrates passing session state values from Django to a Dash app. +

    +
    +
    +

    {% load plotly_dash %}

    +

    <div class="{% plotly_class name="BootstrapApplication"%}"> +

    {% plotly_app name="BootstrapApplication" %}

    +

    <\div> +

    +
    +

    +
    +
    +
    + {%plotly_app name="BootstrapApplication"%} +
    +
    +
    +{%endblock%} diff --git a/demo/demo/templates/index.html b/demo/demo/templates/index.html index 7f419473..d6e727ad 100644 --- a/demo/demo/templates/index.html +++ b/demo/demo/templates/index.html @@ -14,5 +14,6 @@

    Demonstration Application

  • Demo Five - injection of a Dash application without embedding in an html iframe
  • Demo Six - simple html injection example
  • Demo Seven - dash-bootstrap-components example
  • +
  • Demo Eight - Django session state example
  • {%endblock%} diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 75d148a3..832a46fb 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -43,6 +43,7 @@ url('^demo-five$', TemplateView.as_view(template_name='demo_five.html'), name="demo-five"), url('^demo-six', dash_example_1_view, name="demo-six"), url('^demo-seven', TemplateView.as_view(template_name='demo_seven.html'), name="demo-seven"), + url('^demo-eight', TemplateView.as_view(template_name='demo_eight.html'), name="demo-eight"), url('^admin/', admin.site.urls), url('^django_plotly_dash/', include('django_plotly_dash.urls')), From 88dcf1547f3df60d0c0db15d0e005c5a75d87fd5 Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sat, 12 Jan 2019 23:39:23 -0800 Subject: [PATCH 07/10] Adapt boostrap demo --- demo/demo/bootstrap_app.py | 10 ++++++++++ demo/demo/templates/demo_eight.html | 11 +++++++---- demo/demo/urls.py | 4 ++-- demo/demo/views.py | 16 ++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/demo/demo/bootstrap_app.py b/demo/demo/bootstrap_app.py index cfa180af..9f028745 100644 --- a/demo/demo/bootstrap_app.py +++ b/demo/demo/bootstrap_app.py @@ -38,3 +38,13 @@ ] ) +dis = DjangoDash("DjangoSessionState", + add_bootstrap_links=True) + +dis.layout = html.Div( + [ + dbc.Alert("This is an alert", color="primary"), + dbc.Alert("Danger", color="danger"), + ] + ) + diff --git a/demo/demo/templates/demo_eight.html b/demo/demo/templates/demo_eight.html index 60a48396..1f7c4d18 100644 --- a/demo/demo/templates/demo_eight.html +++ b/demo/demo/templates/demo_eight.html @@ -8,19 +8,22 @@

    Django Session State

    This example demonstrates passing session state values from Django to a Dash app.

    +

    + The current value of ind_use is {{ind_use}} +

    {% load plotly_dash %}

    -

    <div class="{% plotly_class name="BootstrapApplication"%}"> -

    {% plotly_app name="BootstrapApplication" %}

    +

    <div class="{% plotly_class name="DjangoSessionState"%}"> +

    {% plotly_app name="DjangoSessionState" ratio=0.3 %}

    <\div>

    -
    - {%plotly_app name="BootstrapApplication"%} +
    + {%plotly_app name="DjangoSessionState" ratio=0.3 %}
    diff --git a/demo/demo/urls.py b/demo/demo/urls.py index 832a46fb..0db3cf9e 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -32,7 +32,7 @@ from django_plotly_dash.views import add_to_session -from .views import dash_example_1_view +from .views import dash_example_1_view, session_state_view urlpatterns = [ url('^$', TemplateView.as_view(template_name='index.html'), name="home"), @@ -43,7 +43,7 @@ url('^demo-five$', TemplateView.as_view(template_name='demo_five.html'), name="demo-five"), url('^demo-six', dash_example_1_view, name="demo-six"), url('^demo-seven', TemplateView.as_view(template_name='demo_seven.html'), name="demo-seven"), - url('^demo-eight', TemplateView.as_view(template_name='demo_eight.html'), name="demo-eight"), + url('^demo-eight', session_state_view, {'template_name':'demo_eight.html'}, name="demo-eight"), url('^admin/', admin.site.urls), url('^django_plotly_dash/', include('django_plotly_dash.urls')), diff --git a/demo/demo/views.py b/demo/demo/views.py index b73a2f1f..bbaf782d 100644 --- a/demo/demo/views.py +++ b/demo/demo/views.py @@ -17,3 +17,19 @@ def dash_example_1_view(request, template_name="demo_six.html", **kwargs): request.session['django_plotly_dash'] = dash_context return render(request, template_name=template_name, context=context) + +def session_state_view(request, template_name, **kwargs): + + session = request.session + + demo_count = session.get('demo_eight_values', {}) + + ind_use = demo_count.get('ind_use', 0) + ind_use += 1 + demo_count['ind_use'] = ind_use + + context = {'ind_use' : ind_use} + + session['demo_eight_values'] = demo_count + + return render(request, template_name=template_name, context=context) From 8ff4640278b119c31b11f601d2a689d31474c9ff Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Sat, 26 Jan 2019 22:57:11 -0800 Subject: [PATCH 08/10] Extended session state demo to include state set in view and dash app --- demo/demo/bootstrap_app.py | 33 +++++++++++++++++++++++++++-- demo/demo/templates/demo_eight.html | 8 ++++++- demo/demo/views.py | 4 ++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/demo/demo/bootstrap_app.py b/demo/demo/bootstrap_app.py index c08e5aed..bef5074b 100644 --- a/demo/demo/bootstrap_app.py +++ b/demo/demo/bootstrap_app.py @@ -22,6 +22,7 @@ SOFTWARE. ''' +import dash import dash_bootstrap_components as dbc import dash_html_components as html @@ -42,8 +43,36 @@ dis.layout = html.Div( [ - dbc.Alert("This is an alert", color="primary"), - dbc.Alert("Danger", color="danger"), + dbc.Alert("This is an alert", id="base-alert", color="primary"), + dbc.Alert(children="Danger", id="danger-alert", color="danger"), + dbc.Button("Update session state", id="update-button", color="warning"), ] ) +@dis.expanded_callback( + dash.dependencies.Output("base-alert", 'children'), + [dash.dependencies.Input('danger-alert', 'children'),] + ) +def session_demo_danger_callback(da_children, session_state=None, **kwargs): + # Update outpue based just on state + if not session_state: + return "Session state not yet available" + + return "Session state contains: " + str(session_state.get('bootstrap_demo_state', "NOTHING")) + " and the page render count is " + str(session_state.get("ind_use","NOT SET")) + +@dis.expanded_callback( + dash.dependencies.Output("danger-alert", 'children'), + [dash.dependencies.Input('update-button', 'n_clicks'),] + ) +def session_demo_danger_callback(n_clicks, session_state=None, **kwargs): + if session_state is None: + raise NotImplementedError("Cannot handle a missing session state") + csf = session_state.get('bootstrap_demo_state', None) + if not csf: + csf = dict(clicks=0) + session_state['bootstrap_demo_state'] = csf + else: + csf['clicks'] = n_clicks + return "Button has been clicked %s times since the page was rendered" %n_clicks + + diff --git a/demo/demo/templates/demo_eight.html b/demo/demo/templates/demo_eight.html index 1f7c4d18..833721c5 100644 --- a/demo/demo/templates/demo_eight.html +++ b/demo/demo/templates/demo_eight.html @@ -9,8 +9,14 @@

    Django Session State

    This example demonstrates passing session state values from Django to a Dash app.

    - The current value of ind_use is {{ind_use}} + The view that renders this page updates a variable each time + the view is rendered in this session. Clicking on the button will update the session + with a record of the number of clicks of the button since the page was rendered.

    +

    + The current page render count in this session is {{ind_use}} +

    +

    {% load plotly_dash %}

    diff --git a/demo/demo/views.py b/demo/demo/views.py index bbaf782d..65dcf43f 100644 --- a/demo/demo/views.py +++ b/demo/demo/views.py @@ -22,7 +22,7 @@ def session_state_view(request, template_name, **kwargs): session = request.session - demo_count = session.get('demo_eight_values', {}) + demo_count = session.get('django_plotly_dash', {}) ind_use = demo_count.get('ind_use', 0) ind_use += 1 @@ -30,6 +30,6 @@ def session_state_view(request, template_name, **kwargs): context = {'ind_use' : ind_use} - session['demo_eight_values'] = demo_count + session['django_plotly_dash'] = demo_count return render(request, template_name=template_name, context=context) From 879b408a3126fa02113d5422b2b442fea03396f2 Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Mon, 28 Jan 2019 12:19:20 -0800 Subject: [PATCH 09/10] Added documentation of demo eight --- demo/demo/bootstrap_app.py | 2 +- docs/demo_notes.rst | 124 ++++++++++++++++++++++++++++++++++++ docs/extended_callbacks.rst | 3 + docs/index.rst | 1 + docs/installation.rst | 5 +- 5 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 docs/demo_notes.rst diff --git a/demo/demo/bootstrap_app.py b/demo/demo/bootstrap_app.py index bef5074b..893cf371 100644 --- a/demo/demo/bootstrap_app.py +++ b/demo/demo/bootstrap_app.py @@ -54,7 +54,7 @@ [dash.dependencies.Input('danger-alert', 'children'),] ) def session_demo_danger_callback(da_children, session_state=None, **kwargs): - # Update outpue based just on state + # Update output based just on state if not session_state: return "Session state not yet available" diff --git a/docs/demo_notes.rst b/docs/demo_notes.rst new file mode 100644 index 00000000..57eee2b8 --- /dev/null +++ b/docs/demo_notes.rst @@ -0,0 +1,124 @@ +.. _demo_notes: + +Demonstration application +========================= + +There are a number of pages in the demo application in the +source repository. + +#. Direct insertion of one or more dash applications +#. Initial state storage within Django +#. Enhanced callbacks +#. Live updating +#. Injection without using an iframe +#. Simple html injection +#. Bootstrap components +#. Session state storage + +The templates that drive each of these can be found in +the `github repository `_. + +There is a more details walkthrough of the :ref:`session state storage ` example. This example also +shows the use of `dash bootstrap components `_. + +.. _session_example: +Session state example walkthrough +--------------------------------- + +The session state example has three separate components in the demo application + +* A template to render the application +* The ``django-plotly-dash`` application itself +* A view to render the template having initialised the session state if needed + +The first of these is a standard Django template, containing instructions to +render the Dash application:: + + {%load plotly-dash%} + + ... + +
    + {%plotly_app name="DjangoSessionState" ratio=0.3 %} +
    + +The view sets up the initial state of the application prior to rendering. For this example +we have a simple variant of rendering a template view:: + + def session_state_view(request, template_name, **kwargs): + + # Set up a context dict here + context = { ... values for template go here, see below ... } + + return render(request, template_name=template_name, context=context) + +and it suffices to register this view at a convenient URL as it does not +use any parameters:: + + ... + url('^demo-eight', + session_state_view, + {'template_name':'demo_eight.html'}, + name="demo-eight"), + ... + +In passing, we note that accepting parameters as part of the URL and passing them as initial +parameters to the app through the template is a straightforward extension of this example. + +The session state can be accessed in the app as well as the view. The app is essentially formed +from a layout function and a number of callbacks. In this particular example, +`dash-bootstrap-components `_ +are used to form the layout:: + + dis = DjangoDash("DjangoSessionState", + add_bootstrap_links=True) + + dis.layout = html.Div( + [ + dbc.Alert("This is an alert", id="base-alert", color="primary"), + dbc.Alert(children="Danger", id="danger-alert", color="danger"), + dbc.Button("Update session state", id="update-button", color="warning"), + ] + ) + +Within the :ref:`expanded callback `, the session state is passed as an extra +argument compared to the standard ``Dash`` callback:: + + @dis.expanded_callback( + dash.dependencies.Output("danger-alert", 'children'), + [dash.dependencies.Input('update-button', 'n_clicks'),] + ) + def session_demo_danger_callback(n_clicks, session_state=None, **kwargs): + if session_state is None: + raise NotImplementedError("Cannot handle a missing session state") + csf = session_state.get('bootstrap_demo_state', None) + if not csf: + csf = dict(clicks=0) + session_state['bootstrap_demo_state'] = csf + else: + csf['clicks'] = n_clicks + return "Button has been clicked %s times since the page was rendered" %n_clicks + +The session state is also set during the view:: + + def session_state_view(request, template_name, **kwargs): + + session = request.session + + demo_count = session.get('django_plotly_dash', {}) + + ind_use = demo_count.get('ind_use', 0) + ind_use += 1 + demo_count['ind_use'] = ind_use + session['django_plotly_dash'] = demo_count + + # Use some of the information during template rendering + context = {'ind_use' : ind_use} + + return render(request, template_name=template_name, context=context) + +Reloading the demonstration page will cause the page render count to be incremented, and the +button click count to be reset. Loading the page in a different session, for example by using +a different browser or machine, will have an independent render count. + + diff --git a/docs/extended_callbacks.rst b/docs/extended_callbacks.rst index 346399e6..158ee819 100644 --- a/docs/extended_callbacks.rst +++ b/docs/extended_callbacks.rst @@ -54,6 +54,9 @@ in the :ref:`models_and_state` section. Using session state ------------------- +The :ref:`walkthrough ` of the session state example details how +the XXX demo interacts with a ``Django`` session. + Unless an explicit pipe is created, changes to the session state and other server-side objects are not automatically propagated to an application. Something in the front-end UI has to invoke a callback; at this point the latest version of these objects will be provided to the callback. The same considerations diff --git a/docs/index.rst b/docs/index.rst index 1a7a87db..5776165b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,6 +23,7 @@ Contents template_tags dash_components configuration + demo_notes access_control faq development diff --git a/docs/installation.rst b/docs/installation.rst index 5a0a92ac..cf4d554a 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -90,7 +90,7 @@ This includes arranging for Dash assets to be served using the Django ``staticfi Source code and demo -------------------- -The source code repository contains a simple demo application. +The source code repository contains a :ref:`simple demo ` application. To install and run it:: @@ -116,5 +116,6 @@ the ``prepare_redis`` step is skipped then the fourth demo page, exhibiting live More details on setting up a development environment, which is also sufficient for running the demo, can be found in the :ref:`development ` section. -Note that the current demo, along with the codebase, is in a prerelease and very raw form. +Note that the current demo, along with the codebase, is in a prerelease and very raw form. An +overview can be found in the :ref:`demonstration application` section.` From 891c8af7790871365dcb8c2285f37787cbdec81d Mon Sep 17 00:00:00 2001 From: Mark Gibbs Date: Mon, 28 Jan 2019 12:34:27 -0800 Subject: [PATCH 10/10] Linter suggestions --- demo/demo/bootstrap_app.py | 18 ++++++++++-------- demo/demo/views.py | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/demo/demo/bootstrap_app.py b/demo/demo/bootstrap_app.py index 893cf371..a06220d6 100644 --- a/demo/demo/bootstrap_app.py +++ b/demo/demo/bootstrap_app.py @@ -43,28 +43,31 @@ dis.layout = html.Div( [ - dbc.Alert("This is an alert", id="base-alert", color="primary"), - dbc.Alert(children="Danger", id="danger-alert", color="danger"), - dbc.Button("Update session state", id="update-button", color="warning"), - ] + dbc.Alert("This is an alert", id="base-alert", color="primary"), + dbc.Alert(children="Danger", id="danger-alert", color="danger"), + dbc.Button("Update session state", id="update-button", color="warning"), + ] ) +#pylint: ignore=unused-argument @dis.expanded_callback( dash.dependencies.Output("base-alert", 'children'), [dash.dependencies.Input('danger-alert', 'children'),] ) def session_demo_danger_callback(da_children, session_state=None, **kwargs): - # Update output based just on state + 'Update output based just on state' if not session_state: return "Session state not yet available" - return "Session state contains: " + str(session_state.get('bootstrap_demo_state', "NOTHING")) + " and the page render count is " + str(session_state.get("ind_use","NOT SET")) + return "Session state contains: " + str(session_state.get('bootstrap_demo_state', "NOTHING")) + " and the page render count is " + str(session_state.get("ind_use", "NOT SET")) +#pylint: ignore=unused-argument @dis.expanded_callback( dash.dependencies.Output("danger-alert", 'children'), [dash.dependencies.Input('update-button', 'n_clicks'),] ) -def session_demo_danger_callback(n_clicks, session_state=None, **kwargs): +def session_demo_alert_callback(n_clicks, session_state=None, **kwargs): + 'Output text based on both app state and session state' if session_state is None: raise NotImplementedError("Cannot handle a missing session state") csf = session_state.get('bootstrap_demo_state', None) @@ -75,4 +78,3 @@ def session_demo_danger_callback(n_clicks, session_state=None, **kwargs): csf['clicks'] = n_clicks return "Button has been clicked %s times since the page was rendered" %n_clicks - diff --git a/demo/demo/views.py b/demo/demo/views.py index 65dcf43f..3b9559be 100644 --- a/demo/demo/views.py +++ b/demo/demo/views.py @@ -19,6 +19,7 @@ def dash_example_1_view(request, template_name="demo_six.html", **kwargs): return render(request, template_name=template_name, context=context) def session_state_view(request, template_name, **kwargs): + 'Example view that exhibits the use of sessions to store state' session = request.session