Giter VIP home page Giter VIP logo

slapdash's Introduction

Slapdash

Boilerplate for bootstrapping scalable multi-page Dash applications

Dash is a Python framework for building analytical web applications. Slapdash provides a sensible project layout for quickly building out a multi-page Dash application with room for growth. It also includes:

  • A skeleton Dash app with multi-pages built using Dash Pages.
  • Pre-built layouts built with Dash Bootstrap Components), which can be extended or swapped out for layouts constructed using your own Dash/CSS components.
  • Scripts for conveniently launching your app in both dev and prod environments

This project is intended for bootstrapping initial Dash applications, rather than being a dependency for your application. You shouldn't assume that Slapdash's internal structure and interfaces will be stable, as they will change.

Boilerplate Overview

  • app.py Entry point into the app. Creates both the Flask and Dash instances used for the app and then imports the rest of the app through the index module. at.
  • settings.py Configurable settings for the application.
  • exceptions.py Exceptions used by your app can be defined here.
  • components.py Convenient Python pseudo-Dash components are defined here.
  • utils.py Utility things.
  • wsgi.py Contains the Flask application attribute for pointing WSGI servers
  • pages/ Place Python modules corresponding to your pages in here.
  • assets/ Location for static assets that will be exposed to the web server.

Installation

Note: Slapdash requires Python 3.6+

Slapdash is a Cookiecutter project. This means you first need to generate your own project from the Slapdash project template.

Install the latest Cookiecutter if you haven't installed it yet:

pip install -U cookiecutter

Generate your project by running this command and following the prompts:

cookiecutter https://github.com/ned2/slapdash

The resulting project is a Python package, which you then need to install like so:

$ pip install PATH_TO_PROJECT

During development you will likely want to perform an editable install so that changes to the source code take immediate effect on the installed package.

$ pip install -e PATH_TO_PROJECT

Usage

  1. In app.py, select the main layout you want from layouts.py.
  2. Create the pages of your app in different files within the pages directory, by defining within each a top-level layout variable or function and callbacks registered using the dash.callback decorator.
  3. Modify assets/app.css or add additional stylesheets in assets.
  4. Modify config in settings.py as required.

Run Dev App

Installing this package into your virtualenv will result into the development executable being installed into your path when the virtualenv is activated. This command invokes your Dash app's run_server method, which in turn uses the Flask development server to run your app. The command is invoked as follows, with proj_slug being replaced by the value provided for this cookiecutter parameter.

$ run-<app>-dev

The script takes a couple of arguments optional parameters, which you can discover with the --help flag. You may need to set the port using the --port parameter. If you need to expose your app outside your local machine, you will want to set --host 0.0.0.0.

Run Prod App

While convenient, the development webserver should not be used in production. Installing this package will also result in a production executable being installed in your virtualenv. This is a wrapper around the mod_wsgi-express command, which streamlines use of the mod_wsgi Apache module to run your your app. In addition to installing the mod_wsgi Python package, you will need to have installed Apache. See installation instructions in the mod_wsgi documentation. This script also takes a range of command line arguments, which can be discovered with the --help flag.

$ run-<app>-prod

This script will also apply settings found in the module project_slug.prod_settings (or a custom Python file supplied with the --settings flag) and which takes precedence over the same settings found in project_slug.settings.

A notable advantage of using mod_wsgi over other WSGI servers is that we do not need to configure and run a web server separate to the WSGI server. When using other WSGI servers (such as Gunicorn or uWSGI), you do not want to expose them directly to web requests from the outside world for two reasons: 1) incoming requests will not be buffered, exposing you to potential denial of service attacks, and 2) you will be serving your static assets via Dash's Flask instance, which is slow. The production script uses mod_wsgi-express to spin up an Apache process (separate to any process already running and listening on port 80) that will buffer requests, passing them off to the worker processes running your app, and will also set up the Apache instance to serve your static assets much faster than would be the case through the Python worker processes.

Note: You will need to reinstall this package in order for changes to the prod script to take effect even if you used an editable install (ie pip install -e).

Running with a different WSGI Server

You can easily run your app using a WSGI server of your choice (such as Gunicorn for example) with the project_slug.wsgi entry point (defined in wsgi.py) like so:

$ gunicorn <app>.wsgi

Note: if you want to enable Dash's debug mode while running with a WSGI server, you'll need to export the DASH_DEBUG environment variable to true. See the Dev Tools section of the Dash Docs for more details.

Included Libraries

Besides Dash itself, Slapdash builds on a few libraries for getting fully functional applications off the ground faster. These include:

  • Dash Bootstrap Components: A suite of Dash components that wrap Bootstrap classes, allowing for cleaner integration of Bootstrap with Dash layouts.
  • Font Awesome - Local copy of Font Awesome files for offline access. Because everyone wants pretty icons.

Useful References

  1. The Dash User Guide

  2. Plotly Python client figure reference Documents the contents of plotly.graph_objs, which contains the different types of charts available, as well the Layout class, for customising the appearance of charts.

  3. The Dash Community Forum

  4. Dash Show and Tell Community Thread

  5. The Dash GitHub Repository

Contributing

PRs are welcome! If you have broader changes in mind, then creating an issue first for discussion would be best.

Seeting up a Dev Environment

After changing directory to the top level Slapdash directory:

  1. Install Slapdash into your virtualenv:
    $ pip install -e .
    
  2. Install the development requirements:
    $ pip install -r requirements-dev.txt
    
  3. Install the pre-commit hook (for the Black code formatter)
    $ pre-commit install
    

slapdash's People

Contributors

ned2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slapdash's Issues

Input('url','pathname') Not Working

Converting some existing code from another project over into slapdash, it seems like Input('url','pathname') cannot be used?

Am I missing something? ...Is there another way to use the url in a callback?

@app.callback(Output('api-connections', 'children'),
              [Input('submit-settings-button', 'n_clicks'),
               Input('url','pathname')])
def update_api_connection_status(n_clicks, pathname):
    if n_clicks and n_clicks > 0:
        print(pathname)
        return html.Div(children=[
            html.Div(className='twelve columns', children=[check_oura_connection()]),
            html.Div(className='twelve columns', children=[check_strava_connection()]),
            html.Div(className='twelve columns', children=[check_withings_connection()])
        ])

Document availability of Flask instance storing Dash params

Slapdash is setup to use the Flask instance's config object to store Dash parameters. These are updated after Dash.init is called, so that they are safe to be used at runtimem via Flask's convenient current_app global. This means we can access Dash config without having to worry about import order

SubPage Implementation

Hey! This is an amazing example and I have been finding it super useful. But I'm looking for each page to have their own subpages. How would I go about that using your infrastructure?

Thanks!

login and @login_required-type functionality

Slapdash is great! Thanks for making this, and for all your other work on Dash.

I'm pretty new to Flask but I've figured out how to implement login, registering, etc. in basic Dash+Flask using flask-login. But in Slapdash it's not super clear to me how I can implement my own functions for login, logout, etc. and use extension decorators - for example, to protect certain pages with @login_required but leave others open (e.g. a public blog for a private product).

How would I go about doing that? Explanations and links appreciated equally.

Docker setup?

Hey @ned2 - first off thanks for this amazing repo, it has helped me organize my own project substantially.

I'm working on a project that would let users self-host an analytical fitness application:
https://github.com/ethanopp/fitly

I'd like to add the ability for the users to be able to deploy via docker, and I currently have it working with the following docker-compose, but saw some benefits in your readme on using the apache prod script instead of an external (gunicorn in this case) server:

version: '3'
services:
  letsencrypt:
    image: linuxserver/letsencrypt
    container_name: letsencrypt 
    cap_add:
      - NET_ADMIN
    restart: always
    ports:
      - "80:80"
      - "443:443"
    environment:
      - PUID=1000
      - PGID=100
      - TZ=America/New_York
      - EMAIL=<your email>
      - URL=<website.com>
      - SUBDOMAINS=fit # this would give a website like fit.website.com
    volumes:
      - /share/CACHEDEV2_DATA/Container/LetsEncrypt:/config
  fitly:
    build:
      dockerfile: Dockerfile
    container_name: fitly
    restart: always
    depends_on:
      - letsencrypt
    ports:
      - "8050:80"
    environment:
      - MODULE_NAME=src.fitly.app
      - VARIABLE_NAME=server
      - TZ=America/New_York
      - TIMEOUT=1200
      - PUID=1000
      - PGID=100
      - DASH_DEBUG=true
    volumes:
      - /share/CACHEDEV2_DATA/Container/Fitly-Slap/fitness.db:/app/fitness.db
      - /share/CACHEDEV2_DATA/Container/Fitly-Slap/config.ini:/app/config.ini
      - /share/CACHEDEV2_DATA/Container/Fitly-Slap/log.log:/app/log.log
      - /share/CACHEDEV2_DATA/Container/Fitly-Slap/gunicorn_conf.py:/gunicorn_conf.py
      - /share/CACHEDEV2_DATA/Container/LetsEncrypt/keys:/app/keys

where fitly is built on the following Dockerfile:

FROM tiangolo/meinheld-gunicorn:python3.7
LABEL maintainer="maintainer"
RUN git clone https://github.com/ethanopp/fitly.git
RUN pip install -U pip && pip install -r ./fitly/requirements.txt
RUN mv ./fitly/* /app/ && rm -rf ./fitly
ENV NGINX_WORKER_PROCESSES auto

Would you happen to have any docs on how to get a docker container stood up which leverages the run-slug-prod script in your repo? Also just in general, is it worth it to switch over towards leveraging that approach or given that the users will most likely just be pulling the repo and deploying (not editing prod_settings, etc.), is the above okay?

datatable_experiments does not display

Love the boilerplate mate! Keep up with the good work.

I am trying to implement one of the datatables (via import dash_table_experiments ) but they do not seem to work. Take the code from this example:

_pages.py_

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt

import pandas as pd
import json
import pandas as pd
import plotly

from .components import Col, Row

page1 = html.Div([
    dt.DataTable(
        id='datatable',
        rows=[
            {'x': 1, 'y': 3},
            {'x': 2, 'y': 10}
        ],
        columns=['x'],
        filterable=True,
        filters={
          "x": {
            "column": {
              "sortable": True,
              "name": "x",
              "filterable": True,
              "editable": True,
              "width": 673,
              "rowType": "filter",
              "key": "x",
              "left": 673
            },
            "filterTerm": "2"
          }
        }
    ),
    html.Div(id='content')
])
_callbacks.py_

@app.callback(Output('content', 'children'), [Input('datatable', 'filters')])
def display_filters(filters):
    return html.Pre(json.dumps(filters, indent=2))

When I run this, I not seem to get any errors but it doesnt display the table as it should. Could you perhaps have a quick look?

Remove usage of Events

Events are being phased out from Dash. Need to remove the various references throughout Slapdash to them.

Consider including dash-bootstrap-components

Rather than just providing Row and Column, by including dash-bootstrap-components, you could provide a default sidebar layout or something like that.

People starting out with Shiny tend to get shown nice bootstrap layouts in the getting-started guides, so it has more of a wow factor for beginners.

run-slapdashed_app-prod

Hi @ned2, I appreciate this is issue might be related to #27 but the error is a bit different and I'm not sure it's related. Apologies if this is an error related to my system (Windows 10 pro, Python 3.8.3) and not slapdash.

I ran almost exactly the same commands as chubukov:

python -m venv slap_env
slap_env\Scripts\activate
python -m pip install cookiecutter
cookiecutter https://github.com/ned2/slapdash
python -m pip install -e slapdashed_app/

I can run-slapdashed_app-dev fine but if I try to run-slapdashed_app-prod I get this error, which seems odd:

'run-slapdashed_app-prod' is not recognized as an internal or external command, operable program or batch file.

Adding the path to my environment variables, which is what I'd normally do, doesn't seem like the right solution to me. I've read through your readme file but I feel like I'm missing something.

Freshly baked Slapdash app should come with basic integration tests

Slapdash comes with some round-trip tests to verify that the cookiecutter recipe, when baked, will successfully create a functioning Dash app and eg its multi-page routes work.

The recipe should be enhanced so that after baking your app, it comes with analogous smoke tests so that you can verify your app at least runs and all expected routes are accessible.

CSS assets do not seem to load when running in PyCharm

I notice the bootstrap.min.css and custom.css files in the slapdash/assets folder, along with FontAwesome. However, these assets do not seem to load when running the app:

screenshot_20181029_120436

When I navigate to the /assets route in the browser, it says "no page '/assets'".

I ran the project in PyCharm by running the run_flask.py file after installing slapdash in the virtual environment.

readme - sections `run-slapdash-dev` and `run-slapdash-prod` are innacurate

great project.

Getting set up was tricky, partly because the readme is incorrect.

Installing this package into your virtualenv will result into the run-slapdash-dev executable being installed into the same virtualenv.

the script is called run-<project-name>-dev . the same for prod.

Also, maybe its because I'm running pyenv or virtualenvwrapper, but the virtualenv exists in ~/.virtualenvs/<venv-name> and therefore running the command takes extra steps - either type the path to the venv, or add my venv to PATH.

slapdash.py?

Your instructions mention to update slapdash.py, but it doesn't exist in the source code.

Document layouts as callables URL query params

The router now accepts callables for layout values. These callables take a single argument which is a werkzeug.datastructures.MultiDict containing the parsed URL query parameters (eg the things after the '?' in pathname?param1=foo&param2=blah)

Need to document this

Preventing Flask termination when exceptions are raised?

Hi,

This is fantastic and perfect for our needs. One challenge I am having (with Dash in general) and hoping there might be a way to address it as part of a config or set up parameter: Flask's default behaviour is to keep the server running when a Python exception is raised. You then get to see the exception in the browser. For some reason, Dash's Flask blueprint does not do this and the server process terminates. Any ideas on how to "fix" this? As a Python newbie, I would tend to make more mistakes in development than most. Having to restart the server every time I hit a syntax or other soon becomes very onerous.

incomplete installation?

I must be doing something wrong during installation. I set up a virtualenv and then followed all the commands, with defaults when prompted. I can get run-slapdashed-app-dev to work fine, but when I try to run run-slapdashed-app-prod I get ModuleNotFoundError: No module named 'slapdash' (and also mod_wsgi errors). Also, I don't see any reference to project_slug.wsgi as mentioned in the docs.

Here's exactly what I did:

python3.6 -m venv slap_env
slap_env/bin/python -m pip install cookiecutter
slap_env/bin/cookiecutter https://github.com/ned2/slapdash
slap_env/bin/python -m pip install -e slapdashed_app/

Enable callback validation

Out of the box, a dynamic multi-page app like Slapdash requires callback validation to be turned off as callbacks will need to be defined that don't yet exist in the layout. the Dash docs have an example in the section titled "Dynamically Create a Layout for Multi-Page App Validation" that show how you can not suppress callback validation.

Use Waitress with Slapdash?

Slapdash is great for developing my Dash app.
Unfortunately, I am too much of a newbie to get slapdash working with waitress, on Windows 10 and Mac OSX.
I tried to point to the wsgi.py file.
I suppose I have to import waitress there, but I don’t know how.
Can you help me with that?

Best regards, Rob

pip install error "no such option: -s"

The README says to install slapdash with the command pip install -s .. However, that command gives an error:

no such option: -s

Environment

pip version: 18.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.