Skip to content

Commit 92a35de

Browse files
Merge pull request #11 from delsim/doc_tweaks
Prerelease 0.4.3
2 parents bcafcd4 + cc6767c commit 92a35de

21 files changed

+292
-88
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Then, just add `django_plotly_dash` to `INSTALLED_APPS` in your Django `settings
2929
...
3030
]
3131

32+
Note that this package requires version 2.0 or greater of Django, due to the use of the `path` function for registering routes.
33+
3234
## Demonstration
3335

3436
The source repository contains a demo application. To clone the repo and lauch the demo:

demo/demo/asgi.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import os
2+
import django
3+
from channels.routing import get_default_application
4+
5+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
6+
django.setup()
7+
application = get_default_application()
8+

demo/demo/consumers.py

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ def __init__(self, *args, **kwargs):
1010
global ALL_CONSUMERS
1111
ALL_CONSUMERS.append(self)
1212

13+
print("Creating a MessageConsumer")
14+
print(len(ALL_CONSUMERS))
15+
16+
self.callcount = 0
17+
1318
def connect(self):
1419
self.accept()
1520

@@ -20,6 +25,7 @@ def disconnect(self, close_code):
2025
if c != self:
2126
ac.append(c)
2227
ALL_CONSUMERS = ac
28+
return super(MessageConsumer, self).disconnect(close_code)
2329

2430
def send_to_widgets(self, channel_name, label, value):
2531
message = json.dumps({'channel_name':channel_name,
@@ -30,6 +36,16 @@ def send_to_widgets(self, channel_name, label, value):
3036
for c in ALL_CONSUMERS:
3137
c.send(message)
3238

39+
self.callcount += 1
40+
if self.callcount > 10:
41+
import gc
42+
print("Running collection")
43+
gc.collect()
44+
self.callcount = 0
45+
46+
import objgraph
47+
objgraph.show_most_common_types()
48+
3349
def receive(self, text_data):
3450
message = json.loads(text_data)
3551

demo/demo/plotly_apps.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ def callback_size(dropdown_color, dropdown_size):
5252
)
5353
def callback_c(*args,**kwargs):
5454
da = kwargs['dash_app']
55+
56+
session_state = kwargs['session_state']
57+
58+
calls_so_far = session_state.get('calls_so_far',0)
59+
session_state['calls_so_far'] = calls_so_far + 1
60+
61+
user_counts = session_state.get('user_counts',None)
62+
user_name = str(kwargs['user'])
63+
if user_counts is None:
64+
user_counts = {user_name:1}
65+
session_state['user_counts'] = user_counts
66+
else:
67+
user_counts[user_name] = user_counts.get(user_name,0) + 1
68+
5569
return "Args are [%s] and kwargs are %s" %(",".join(args),str(kwargs))
5670

5771
a3 = DjangoDash("Connected")
@@ -67,7 +81,6 @@ def callback_c(*args,**kwargs):
6781
label="momentum",
6882
channel_name="test_widget_channel",
6983
uid="and_this_one"),
70-
dpd.DPDirectComponent(id="direct"),
7184
dcc.RadioItems(id="dropdown-one",options=[{'label':i,'value':j} for i,j in [
7285
("O2","Oxygen"),("N2","Nitrogen"),("CO2","Carbon Dioxide")]
7386
],value="Oxygen"),

demo/demo/settings.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
'django.contrib.staticfiles',
4040

4141
'channels',
42+
'bootstrap4',
4243

4344
'django_plotly_dash.apps.DjangoPlotlyDashConfig',
4445
]
@@ -126,14 +127,22 @@
126127
STATIC_ROOT = os.path.join(BASE_DIR,'static')
127128

128129
STATICFILES_DIRS = [
130+
os.path.join(BASE_DIR,'demo','static'),
129131
]
130132

131-
import dash_core_components as dcc
132-
_rname = os.path.join(os.path.dirname(dcc.__file__),'..')
133-
for dash_module_name in ['dash_core_components',
134-
'dash_html_components',
135-
'dash_renderer',]:
136-
STATICFILES_DIRS.append( ("dash/%s"%dash_module_name, os.path.join(_rname,dash_module_name)) )
133+
# In order to serve dash components locally - not recommended in general, but
134+
# can be useful for development especially if offline - we add in the root directory
135+
# of each module. This is a bit of fudge and only needed if serve_locally=True is
136+
# set on a DjangoDash instance.
137+
138+
if DEBUG:
139+
140+
import dash_core_components as dcc
141+
_rname = os.path.join(os.path.dirname(dcc.__file__),'..')
142+
143+
for dash_module_name in ['dash_core_components',
144+
'dash_html_components',
145+
'dash_renderer',
146+
'dpd_components',]:
147+
STATICFILES_DIRS.append( ("dash/%s"%dash_module_name, os.path.join(_rname,dash_module_name)) )
137148

138-
# Fudge to work with channels in debug mode
139-
STATICFILES_DIRS.append(("dash/dpd_components","/home/mark/local/dpd-components/lib"))

demo/demo/static/demo/demo.css

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* Extra CSS markup for demo pages */
2+
3+
.btnspace { margin-bottom: 10px; }
4+
5+
.dpd-example-wrapper { background-color: #e0e0e0; padding: 10px; }
6+
.dpd-example { background-color: white; }

demo/demo/templates/base.html

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
<head>
4+
{%load plotly_dash%}
5+
{%load staticfiles%}
6+
{%load bootstrap4%}
7+
{%bootstrap_css%}
8+
{%bootstrap_javascript jquery="full"%}
9+
<link rel="stylesheet" type="text/css" href="{%static "demo/demo.css"%}"></link>
10+
<title>Django Plotly Dash Examples - {%block title%}{%endblock%}</title>
11+
</head>
12+
<body>
13+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
14+
<div class="navbar-nav">
15+
<a class="navbar-brand" href="#">
16+
<img src="{%static "demo/logo.svg"%}" alt="Logo"/>
17+
</a>
18+
<a class="nav-item nav-link btn btn-lg" href="{%url "home"%}">Contents</a>
19+
<a class="nav-item nav-link btn btn-lg" href="{%url "demo-one"%}">Demo One - Simple Use</a>
20+
<a class="nav-item nav-link btn btn-lg" href="{%url "demo-two"%}">Demo Two - Initial State</a>
21+
<a class="nav-item nav-link btn btn-lg" href="{%url "demo-three"%}">Demo Three - Enhanced Callbacks</a>
22+
<a class="nav-item nav-link btn btn-lg" href="{%url "demo-four"%}">Demo Four - Live Updating</a>
23+
</div>
24+
</nav>
25+
<div class="container">
26+
{%block content%}{%endblock%}
27+
</div>
28+
</body>
29+
{%block post_body%}{%endblock%}
30+
</html>

demo/demo/templates/demo_four.html

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{%extends "base.html"%}
2+
{%load plotly_dash%}
3+
4+
{%block post_body%}{%plotly_message_pipe%}{%endblock%}
5+
6+
{%block title%}Demo Four - Live Updating{%endblock%}
7+
8+
{%block content%}
9+
<h1>Live Updating</h1>
10+
<p>
11+
Live updating uses a websocket connection. The server pushes messages to the UI, and this is then translated into a
12+
callback through a dash component.
13+
</p>
14+
<div class="card bg-light border-dark">
15+
<div class="card-body">
16+
<p><span>{</span>% load plotly_dash %}</p>
17+
<p><span>{</span>% plotly_app slug="connected-2" %}</p>
18+
</div>
19+
</div>
20+
<p>
21+
</p>
22+
<div class="card border-dark">
23+
<div class="card-body">
24+
{%plotly_app slug="connected-2"%}
25+
</div>
26+
</div>
27+
<p>
28+
</p>
29+
<div class="card border-dark">
30+
<div class="card-body">
31+
{%plotly_app slug="connected-2"%}
32+
</div>
33+
</div>
34+
{%endblock%}

demo/demo/templates/demo_one.html

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{%extends "base.html"%}
2+
{%load plotly_dash%}
3+
4+
{%block title%}Demo One - Simple Embedding{%endblock%}
5+
6+
{%block content%}
7+
<h1>Simple App Embedding</h1>
8+
<p>
9+
This is a simple example of use of a dash application within a Django template. Use of
10+
the plotly_app template tag with the name of a dash application represents the simplest use of
11+
the django_plotly_dash framework.
12+
</p>
13+
<div class="card bg-light border-dark">
14+
<div class="card-body">
15+
<p><span>{</span>% load plotly_dash %}</p>
16+
<p><span>{</span>% plotly_app name="SimpleExample" %}</p>
17+
</div>
18+
</div>
19+
<p></p>
20+
<div class="card border-dark">
21+
<div class="card-body">
22+
{%plotly_app name="SimpleExample"%}
23+
</div>
24+
</div>
25+
{%endblock%}
26+

demo/demo/templates/demo_three.html

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{%extends "base.html"%}
2+
{%load plotly_dash%}
3+
4+
{%block title%}Demo Three - Additional Callback Functionality{%endblock%}
5+
6+
{%block content%}
7+
<h1>Enhanced Callback Functionality</h1>
8+
<p>
9+
If any callback is registered as an enhanced one, then all of the callbacks receive extra values
10+
as kwargs. These include the Dash application instance, a per-session dictionary that can contain anything
11+
suitable for inclusion in a standard Django session, and the Django User instance.
12+
The session state is per user session at the Django level, so it is shared across all of the Dash applications.
13+
</p>
14+
<p>
15+
Changes made to any values contained within the initial state can also be persisted when using enhanced callbacks. This is a
16+
per-app-instance flag and, when set, the response of every callback is checked and persisted if it has changed. The second
17+
of the two apps below is configured in this manner; any changes made on this page should reappear if one visits a different page and
18+
then reloads this one. These changes can also be observed in the update timestamp or initial content json content of
19+
the <a href="{%url "admin:django_plotly_dash_dashapp_changelist" %}">model</a>.
20+
</p>
21+
<div class="card bg-light border-dark">
22+
<div class="card-body">
23+
<p><span>{</span>% load plotly_dash %}</p>
24+
<p><span>{</span>% plotly_app name="Ex2" ratio=0.15 %}</p>
25+
<p><span>{</span>% plotly_app slug="ex2-3" ratio=0.15 %}</p>
26+
</div>
27+
</div>
28+
<p>
29+
</p>
30+
<div class="card border-dark">
31+
<div class="card-body">
32+
{%plotly_app name="Ex2" ratio=0.15 %}
33+
</div>
34+
</div>
35+
<p>
36+
</p>
37+
<div class="card border-dark">
38+
<div class="card-body">
39+
{%plotly_app slug="ex2-3" ratio=0.15 %}
40+
</div>
41+
</div>
42+
{%endblock%}

demo/demo/templates/demo_two.html

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{%extends "base.html"%}
2+
{%load plotly_dash%}
3+
4+
{%block title%}Demo Two - Initial State{%endblock%}
5+
6+
{%block content%}
7+
<h1>Initial State</h1>
8+
<p>
9+
Referring to an instance of a dash application, uniquely identified by a slug, will use the persisted
10+
representation of that app along with its initial state.
11+
</p>
12+
<p>
13+
Each time this page is reloaded, the application will revert to its stored intial state. This initial
14+
state is persisted in a standard
15+
Django <a href="{%url "admin:django_plotly_dash_dashapp_changelist" %}">model</a>.
16+
</p>
17+
<div class="card bg-light border-dark">
18+
<div class="card-body">
19+
<p><span>{</span>% load plotly_dash %}</p>
20+
<p><span>{</span>% plotly_app slug="simpleexample-1" ratio=0.2 %}</p>
21+
</div>
22+
</div>
23+
<p>
24+
</p>
25+
<div class="card border-dark">
26+
<div class="card-body">
27+
{%plotly_app slug="simpleexample-1" ratio=0.2 %}
28+
</div>
29+
</div>
30+
{%endblock%}

demo/demo/templates/index.html

+15-36
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,15 @@
1-
<!DOCTYPE HTML>
2-
<html>
3-
<head>
4-
{%load plotly_dash%}
5-
<title>Simple stuff</title>
6-
</head>
7-
<body>
8-
<div>
9-
<p>Navigational links :
10-
<a href="{%url "home"%}">Main Page</a>
11-
<a href="{%url "second"%}">Second Page</a>
12-
</p>
13-
</div>
14-
<div>
15-
Content here
16-
{%plotly_app slug="simpleexample-1" ratio=0.2 %}
17-
</div>
18-
<div>
19-
Content here
20-
{%plotly_app name="SimpleExample"%}
21-
</div>
22-
<div>
23-
Content here
24-
{%plotly_app name="Ex2"%}
25-
</div>
26-
<div>
27-
WS Content here
28-
{%plotly_app name="Connected"%}
29-
</div>
30-
<div>
31-
WS Content here
32-
{%plotly_app slug="connected-2"%}
33-
</div>
34-
</body>
35-
{%plotly_message_pipe%}
36-
</html>
1+
{%extends "base.html"%}
2+
{%block title%} Index{%endblock%}
3+
{%block content%}
4+
<h1>Demonstration Application</h1>
5+
<div>
6+
This is the django_plotly_dash demo application. It contains a number of separate pages that
7+
exhibit different features of the integration of Plotly Dash into the Django framework.
8+
</div>
9+
<ul class="btnspace">
10+
<li><a class="btn btn-primary btnspace" href="{%url "demo-one"%}">Demo One</a> - direct insertion of one or more Dash applications into a Django template</li>
11+
<li><a class="btn btn-primary btnspace" href="{%url "demo-two"%}">Demo Two</a> - storage of application initial state within Django</li>
12+
<li><a class="btn btn-primary btnspace" href="{%url "demo-three"%}">Demo Three</a> - adding Django features with enhanced callbacks</li>
13+
<li><a class="btn btn-primary btnspace" href="{%url "demo-four"%}">Demo Four</a> - live updating of apps by pushing from the Django server</li>
14+
</ul>
15+
{%endblock%}

demo/demo/templates/second_page.html

-23
This file was deleted.

0 commit comments

Comments
 (0)