diff --git a/README.md b/README.md index aaceaab3..f2a2070e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,102 @@ # django-plotly-dash -Expose plotly dash apps as django tags. +Expose [plotly dash](https://plot.ly/products/dash/) apps as django tags. See the source for this project here: -. + + +Online documentation can be found here: + + +## Installation + +First, install the package. This will also install plotly and some dash packages if they are not already present. + + pip install django_plotly_dash + +Then, just add `django_plotly_dash` to `INSTALLED_APPS` in your Django `settings.py` file + + INSTALLED_APPS = [ + ... + 'django_plotly_dash', + ... + ] + +## Demonstration + +The source repository contains a demo application. To clone the repo and lauch the demo: + +```bash +git clone https://github.com/GibbsConsulting/django-plotly-dash.git + +cd django-plotly-dash + +./make_env # sets up a virtual environment for development + # with direct use of the source code for the package + +./prepare_demo # prepares and launches the demo + # using the Django debug server at http://localhost:8000 +``` + +## Usage + +To use existing dash applications, first register them using the `DelayedDash` class. This +replaces the `dash.Dash` class of `plotly.py.` + +Taking as an example a slightly modified variant of one of the [getting started](https://dash.plot.ly/getting-started-part-2) examples: + +```python +import dash +import dash_core_components as dcc +import dash_html_components as html + +from django_plotly_dash import DelayedDash + +app = DelayedDash('SimpleExample') # replaces dash.Dash + +app.layout = html.Div([ + dcc.RadioItems( + id='dropdown-a', + options=[{'label': i, 'value': i} for i in ['Canada', 'USA', 'Mexico']], + value='Canada' + ), + html.Div(id='output-a'), + + dcc.RadioItems( + id='dropdown-b', + options=[{'label': i, 'value': i} for i in ['MTL', 'NYC', 'SF']], + value='MTL' + ), + html.Div(id='output-b') + +]) + +@app.callback( + dash.dependencies.Output('output-a', 'children'), + [dash.dependencies.Input('dropdown-a', 'value')]) +def callback_a(dropdown_value): + return 'You\'ve selected "{}"'.format(dropdown_value) + + +@app.callback( + dash.dependencies.Output('output-b', 'children'), + [dash.dependencies.Input('dropdown-a', 'value'), + dash.dependencies.Input('dropdown-b', 'value')]) +def callback_b(dropdown_value,other_dd): + return 'You\'ve selected "{}" and "{}"'.format(dropdown_value, + other_dd) +``` + +Note that the `DelayedDash` constructor requires a name to be specified. This name is then used to identify the dash app in +templates: + +```jinja2 +{% load plotly_dash %} + +{% plotly_item "SimpleExample" %} +``` + +Note that the registration code needs to be in a location +that will be imported into the Django process before any template tag attempts to use it. The example Django application +in the demo subdirectory achieves this through an import in the main urls.py file; any views.py would also be sufficient. diff --git a/demo/demo/settings.py b/demo/demo/settings.py index e9384973..08964954 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -56,7 +56,7 @@ TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [os.path.join(BASE_DIR,'demo','templates'),], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ diff --git a/demo/demo/templates/index.html b/demo/demo/templates/index.html new file mode 100644 index 00000000..7749878a --- /dev/null +++ b/demo/demo/templates/index.html @@ -0,0 +1,19 @@ + + +{%load plotly_dash%} + Simple stuff + +
+ Content here + {%plotly_item "SimpleExample"%} +
+
+ Content here + {%plotly_item "SimpleExample"%} +
+
+ Content here + {%plotly_item "Ex2"%} +
+ + diff --git a/dev_requirements.txt b/dev_requirements.txt new file mode 100644 index 00000000..a3b7d1d1 --- /dev/null +++ b/dev_requirements.txt @@ -0,0 +1,54 @@ +alabaster==0.7.10 +argh==0.26.2 +Babel==2.5.3 +certifi==2018.4.16 +chardet==3.0.4 +click==6.7 +dash==0.21.1 +dash-core-components==0.22.1 +dash-html-components==0.10.1 +dash-renderer==0.12.1 +decorator==4.3.0 +Django==2.0.5 +-e git+https://github.com/delsim/django-plotly-dash.git@293b454ee8965422155a971d9e417878dc89ce82#egg=django_plotly_dash +docopt==0.6.2 +docutils==0.14 +Flask==1.0.2 +Flask-Compress==1.4.0 +grip==4.5.2 +idna==2.6 +imagesize==1.0.0 +ipython-genutils==0.2.0 +itsdangerous==0.24 +Jinja2==2.10 +jsonschema==2.6.0 +jupyter-core==4.4.0 +livereload==2.5.2 +Markdown==2.6.11 +MarkupSafe==1.0 +nbformat==4.4.0 +packaging==17.1 +path-and-address==2.0.1 +pathtools==0.1.2 +pkginfo==1.4.2 +plotly==2.5.1 +port-for==0.3.1 +Pygments==2.2.0 +pyparsing==2.2.0 +pytz==2018.4 +PyYAML==3.12 +requests==2.18.4 +requests-toolbelt==0.8.0 +six==1.11.0 +snowballstemmer==1.2.1 +Sphinx==1.7.4 +sphinx-autobuild==0.7.1 +sphinx-rtd-theme==0.3.1 +sphinxcontrib-websupport==1.0.1 +tornado==5.0.2 +tqdm==4.23.3 +traitlets==4.3.2 +twine==1.11.0 +urllib3==1.22 +watchdog==0.8.3 +Werkzeug==0.14.1 diff --git a/django_plotly_dash/templatetags/plotly_dash.py b/django_plotly_dash/templatetags/plotly_dash.py new file mode 100644 index 00000000..52fce6e5 --- /dev/null +++ b/django_plotly_dash/templatetags/plotly_dash.py @@ -0,0 +1,13 @@ +from django import template + +register = template.Library() + +from django_plotly_dash.dash_wrapper import get_app_by_name + +@register.inclusion_tag("django_plotly_dash/plotly_item.html", takes_context=True) +def plotly_item(context, app_name): + + app = get_app_by_name(app_name) + url = app.base_url() + + return locals() diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..feb93abe --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = django-plotly-dash +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..d29c14d6 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'django-plotly-dash' +copyright = '2018 Gibbs Consulting, a division of 0802100 (BC) Ltd' +author = 'Mark Gibbs' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +#html_theme = 'alabaster' +html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'django-plotly-dashdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'django-plotly-dash.tex', 'django-plotly-dash Documentation', + 'Mark Gibbs', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'django-plotly-dash', 'django-plotly-dash Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'django-plotly-dash', 'django-plotly-dash Documentation', + author, 'django-plotly-dash', 'One line description of project.', + 'Miscellaneous'), +] diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..07d06acc --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,25 @@ +.. django-plotly-dash documentation master file, created by + sphinx-quickstart on Tue May 8 12:25:40 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to django-plotly-dash's documentation! +============================================== + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + installation + simple_use + + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 00000000..ee12c752 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,38 @@ +.. _installation: + +Installation +============ + +Use pip to install the package, preferably to a local virtualenv.:: + + pip install django_plotly_dash + +Then, add ``django_plotly_dash`` to ``INSTALLED_APPS`` in the Django settings.py file:: + + INSTALLED_APPS = [ + ... + 'django_plotly_dash', + ... + ] + +The plotly_item tag in the plotly_dash tag library can then be used to render any registered dash component. See :ref:`simple_use` for a simple example. + +Source code and demo +-------------------- + +The source code repository contains a simple demo application. + +To install and run it:: + + git clone https://github.com/GibbsConsulting/django-plotly-dash.git + + cd django-plotly-dash + + ./make_env # sets up a virtual environment + # with direct use of the source + # code for the package + + ./prepare_demo # prepares and launches the demo + # using the Django debug server + # at http://localhost:8000 + diff --git a/docs/simple_use.rst b/docs/simple_use.rst new file mode 100644 index 00000000..4d8c863a --- /dev/null +++ b/docs/simple_use.rst @@ -0,0 +1,61 @@ +.. _simple_use: + +Simple Usage +============ + +To use existing dash applications, first register them using the ``DelayedDash`` class. This +replaces the ``dash.Dash`` class of ``plotly.py`` + +Taking as an example a slightly modified variant of one of the `getting started `_ examples:: + + import dash + import dash_core_components as dcc + import dash_html_components as html + + from django_plotly_dash import DelayedDash + + app = DelayedDash('SimpleExample') # replaces dash.Dash + + app.layout = html.Div([ + dcc.RadioItems( + id='dropdown-a', + options=[{'label': i, 'value': i} for i in ['Canada', 'USA', 'Mexico']], + value='Canada' + ), + html.Div(id='output-a'), + + dcc.RadioItems( + id='dropdown-b', + options=[{'label': i, 'value': i} for i in ['MTL', 'NYC', 'SF']], + value='MTL' + ), + html.Div(id='output-b') + + ]) + + @app.callback( + dash.dependencies.Output('output-a', 'children'), + [dash.dependencies.Input('dropdown-a', 'value')]) + def callback_a(dropdown_value): + return 'You\'ve selected "{}"'.format(dropdown_value) + + + @app.callback( + dash.dependencies.Output('output-b', 'children'), + [dash.dependencies.Input('dropdown-a', 'value'), + dash.dependencies.Input('dropdown-b', 'value')]) + def callback_b(dropdown_value,other_dd): + return 'You\'ve selected "{}" and "{}"'.format(dropdown_value, + other_dd) + +Note that the ``DelayedDash`` constructor requires a name to be specified. This name is then used to identify the dash app in +templates::: + + {%load plotly_dash%} + + {%plotly_item "SimpleExample"%} + +Note that the registration code needs to be in a location +that will be imported into the Django process before any template tag attempts to use it. The example Django application +in the demo subdirectory achieves this through an import in the main urls.py file; any views.py would also be sufficient. + diff --git a/requirements.txt b/requirements.txt index 06bf3f7c..4c75f37e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,26 +1,6 @@ -certifi==2018.4.16 -chardet==3.0.4 -click==6.7 dash==0.21.1 dash-core-components==0.22.1 dash-html-components==0.10.1 dash-renderer==0.12.1 -decorator==4.3.0 Django==2.0.5 -Flask==1.0.2 -Flask-Compress==1.4.0 -idna==2.6 -ipython-genutils==0.2.0 -itsdangerous==0.24 -Jinja2==2.10 -jsonschema==2.6.0 -jupyter-core==4.4.0 -MarkupSafe==1.0 -nbformat==4.4.0 plotly==2.5.1 -pytz==2018.4 -requests==2.18.4 -six==1.11.0 -traitlets==4.3.2 -urllib3==1.22 -Werkzeug==0.14.1 diff --git a/setup.py b/setup.py index c177ddea..7c2d790f 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ project_urls = { 'Source': "https://github.com/GibbsConsulting/django-plotly-dash", 'Tracker': "https://github.com/GibbsConsulting/django-plotly-dash/issues", + 'Documentation': 'http://django-plotly-dash.readthedocs.io/', }, install_requires = ['plotly', 'dash', @@ -40,6 +41,5 @@ 'dash-renderer', 'Django',], python_requires=">=3", - )