diff --git a/demo/demo/templates/demo_one.html b/demo/demo/templates/demo_one.html index b91b4fa8..568daf0e 100644 --- a/demo/demo/templates/demo_one.html +++ b/demo/demo/templates/demo_one.html @@ -10,16 +10,25 @@

Simple App Embedding

the plotly_app template tag with the name of a dash application represents the simplest use of the django_plotly_dash framework.

+

+ The plotly_class tag is also used to wrap the application in css class names based on the + application (django-plotly-dash), the + type of the embedding (iframe), and the slugified version of the app name (simpleexample). +

{% load plotly_dash %}

-

{% plotly_app name="SimpleExample" %}

+

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

{% plotly_app name="SimpleExample" %}

+

<\div>

- {%plotly_app name="SimpleExample"%} +
+ {%plotly_app name="SimpleExample"%} +
{%endblock%} diff --git a/django_plotly_dash/dash_wrapper.py b/django_plotly_dash/dash_wrapper.py index 002a80bb..a61ba9e8 100644 --- a/django_plotly_dash/dash_wrapper.py +++ b/django_plotly_dash/dash_wrapper.py @@ -1,4 +1,5 @@ -'''dash_wrapper +''' +dash_wrapper This module provides a DjangoDash class that can be used to expose a Plotly Dasb application through a Django server @@ -196,7 +197,7 @@ def before_first_request(self, *args, **kwargs): pass def run(self, *args, **kwargs): pass - def register_blueprint(*args, **kwargs): + def register_blueprint(self, *args, **kwargs): pass class WrappedDash(Dash): @@ -302,7 +303,7 @@ def flask_app(self): return self._flask_app def base_url(self): - 'Base url of this omponent' + 'Base url of this component' return self._base_pathname def app_context(self, *args, **kwargs): @@ -412,3 +413,28 @@ def dispatch_with_args(self, body, argMap): da.update_current_state(output['id'], output['property'], value) return res + + def slugified_id(self): + 'Return the app id in a slug-friendly form' + pre_slugified_id = self._uid + return slugify(pre_slugified_id) + + def extra_html_properties(self, prefix=None, postfix=None, template_type=None): + ''' + Return extra html properties to allow individual apps to be styled separately. + + The content returned from this function is injected unescaped into templates. + ''' + + prefix = prefix if prefix else "django-plotly-dash" + + post_part = "-%s" % postfix if postfix else "" + template_type = template_type if template_type else "iframe" + + slugified_id = self.slugified_id() + + return "%(prefix)s %(prefix)s-%(template_type)s %(prefix)s-app-%(slugified_id)s%(post_part)s" % {'slugified_id':slugified_id, + 'post_part':post_part, + 'template_type':template_type, + 'prefix':prefix, + } diff --git a/django_plotly_dash/templatetags/plotly_dash.py b/django_plotly_dash/templatetags/plotly_dash.py index b1b331d3..047797b2 100644 --- a/django_plotly_dash/templatetags/plotly_dash.py +++ b/django_plotly_dash/templatetags/plotly_dash.py @@ -72,3 +72,38 @@ def plotly_message_pipe(context, url=None): 'Insert script for providing background websocket connection' url = url if url else ws_default_url return locals() + +@register.simple_tag() +def plotly_app_identifier(name=None, slug=None, da=None, postfix=None): + 'Return a slug-friendly identifier' + if name is not None: + da, app = DashApp.locate_item(name, stateless=True) + + if slug is not None: + da, app = DashApp.locate_item(slug, stateless=False) + + if not app: + app = da.as_dash_instance() + + slugified_id = app.slugified_id() + + if postfix: + return "%s-%s" %(slugified_id, postfix) + return slugified_id + +@register.simple_tag() +def plotly_class(name=None, slug=None, da=None, prefix=None, postfix=None, template_type=None): + 'Return a string of space-separated class names' + + if name is not None: + da, app = DashApp.locate_item(name, stateless=True) + + if slug is not None: + da, app = DashApp.locate_item(slug, stateless=False) + + if not app: + app = da.as_dash_instance() + + return app.extra_html_properties(prefix=prefix, + postfix=postfix, + template_type=template_type) diff --git a/docs/template_tags.rst b/docs/template_tags.rst index ce8a14c0..4e175cc6 100644 --- a/docs/template_tags.rst +++ b/docs/template_tags.rst @@ -54,3 +54,63 @@ on the page, and its ordering relative to the ``Dash`` instances using updating the page footer - to avoid delaying the main page load - along with other scripts is generally advisable. +The ``plotly_app_identifier`` template tag +----------------------------------------- + +This tag provides an identifier for an app, in a form that is suitable for use as a classname or identifier +in HTML: + +.. code-block:: jinja + + {%load plotly_dash%} + + {%plotly_app_identifier name="SimpleExample"%} + + {%plotly_app_identifier slug="liveoutput-2" postfix="A"%} + +The identifier, if the tag is not passed a ``slug``, is the result of passing the identifier of the app through +the ``django.utils.text.slugify`` function. + +The tag arguments are: + +:name = None: The name of the application, as passed to a ``DjangoDash`` constructor. +:slug = None: The slug of an existing ``DashApp`` instance. +:da = None: An existing ``django_plotly_dash.models.DashApp`` model instance. +:postfix = None: An optional string; if specified it is appended to the identifier with a hyphen. + +The validity rules for these arguments are the same as those for the ``plotly_app`` template tag. If +supplied, the ``postfix`` argument +should already be in a slug-friendly form, as no processing is performed on it. + +The ``plotly_class`` template tag +----------------------------------------- + +Generate a string of class names, suitable for a ``div`` or other element that wraps around ``django-plotly-dash`` template content. + +.. code-block:: jinja + + {%load plotly_dash%} + +
+ {%plotly_app slug="liveoutput-2" ratio="0.5" %} +
+ +The identifier, if the tag is not passed a ``slug``, is the result of passing the identifier of the app through +the ``django.utils.text.slugify`` function. + +The tag arguments are: + +:name = None: The name of the application, as passed to a ``DjangoDash`` constructor. +:slug = None: The slug of an existing ``DashApp`` instance. +:da = None: An existing ``django_plotly_dash.models.DashApp`` model instance. +:prefix = None: Optional prefix to use in place of the text ``django-plotly-dash`` in each class name +:postfix = None: An optional string; if specified it is appended to the app-specific identifier with a hyphen. +:template_type = None: Optional text to use in place of ``iframe`` in the template-specific class name + +The tag inserts a string with three class names in it. One is just the ``prefix`` argument, one +has the ``template_type`` appended, and the final one has the app identifier (as generated +by the ``plotly_app_identifier`` tag) and any ``postfix`` appended. + +The validity rules for these arguments are the same as those for the ``plotly_app`` and ``plotly_app_identifier`` template tags. Note +that none of the ``prefix``, ``postfix`` and ``template_type`` arguments are modified and they should +already be in a slug-friendly form, or otherwise fit for their intended purpose.