Краткое руководство по Dash — Python веб-фреймворк для создания дэшбордов. Installation + Dash Layout
Сегодня предлагаю погрузиться в один из удобнейших веб-фреймворков в связке c Python под названием Dash. Появился он не так давно, пару лет назад благодаря разработчикам фреймворка plotly. Сам Dash является связкой Flask, React.Js, HTML и CSS.
Выступление Криса Пармера на PLOTCON 2016
Давайте сразу установим фреймворк. Обновленные версии уточняйте тут.
pip install dash==0.31.1 # The core dash backend pip install dash-html-components==0.13.2 # HTML components pip install dash-core-components==0.38.1 # Supercharged components pip install dash-table==3.1.7 # Interactive DataTable component (new!)
Друзья, если вы действительно хотите разобраться в данном фреймворке, читайте публикации до конца, так как зачастую сначала следуют примеры, а уже после детальный обзор кода. Если вам все равно непонятно — советую читать документацию по Dash на английском языке в оригинале. Также в рунете есть несколько статей, которые объясняют концепции, которые я решил пропустить в данном туториале.
Начнем.
Приложения Dash состоят из двух частей. Первая часть — «layout» описывает то, как выглядит наше приложение. Вторая часть описывает интерактивность приложения, о ней мы поговорим в следующей статье.
Dash предоставляет Python классы для всех визуальных компонентов приложения. Разработчики предоставляют набор компонентов в так называемых dash_core_components и dash_html_components . Но также вы можете построить свой компонент используя JavaScript и React.js.
В dash_core_components содержатся различные динамические формы такие как, например, выпадающие списки, графики и чек-боксы.
В dash_html_components содержатся html конструкции, которыми можно завернуть наши формы. Например Div блоки или теги заголовков H1, H2, и так далее. Разработчики предоставляют нам некую абстракцию от html с помощью словарей Python.
Чтобы начать разбираться, создадим файл app.py , в котором будет содержаться следующее:
# -*- coding: utf-8 -*- # Загрузим необходимые пакеты import dash import dash_core_components as dcc import dash_html_components as html # Объяснение данных строк пока опускается, будет объяснено далее external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div(children=[ html.H1(children='Hello Dash'), html.Div(children=''' Dash: A web application framework for Python. '''), dcc.Graph( , figure=< 'data': [ , , ], 'layout': < 'title': 'Dash Data Visualization' >> ) ]) if __name__ == '__main__': app.run_server(debug=True)
И запустим его из текущей директории командой:
$ python app.py
. Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
Видим, что сервер запустился и готов принимать запросы на порт 8050 (у вас может быть другой порт).
Переходим по адресу http://127.0.0.1:8050/
и видим:
Примечание
- Компонент layout состоит из дерева «компонентов», которые содержаться в dash_html_components . Например блоков Div.
- dash_html_components имеет компонент для каждого html тэга. html.H1(children=’Hello Dash’) компонент генерирует HTML элемент
На заметку
Dash содержит привычную веб разработчика фичу: hot-reloading . Она активируется в тот момент, когда запускается функция app.run_server(debug=True) . Эта фича обновляет ваш браузер всякий раз, когда вы делаете правки в коде и сохраняете результат. Таким образом нет нужды каждый раз перезапускать сервер.
Как мы помним, Dash содержит компонент для каждого тега HTML. Но также он может принимать все аргументы ключевых слов, как и элементы HTML.
Давайте немного изменим наш код:
# -*- coding: utf-8 -*- import dash import dash_core_components as dcc import dash_html_components as html external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) colors = < 'background': '#111111', 'text': '#7FDBFF' >app.layout = html.Div(style=, children=[ html.H1( children='Hello Dash', style= < 'textAlign': 'center', 'color': colors['text'] >), html.Div(children='Dash: A web application framework for Python.', style=< 'textAlign': 'center', 'color': colors['text'] >), dcc.Graph( , figure=< 'data': [ , , ], 'layout': < 'plot_bgcolor': colors['background'], 'paper_bgcolor': colors['background'], 'font': < 'color': colors['text'] >> > ) ]) if __name__ == '__main__': app.run_server(debug=True)
Обновляем страницу, и видим:
В этом примере мы изменили стили html.Div и html.H1 с помощью свойства style .
html.H1(‘Hello Dash’, style=) отрендерится в приложении Dash как:
Но есть несколько важных замечаний:
- Свойства style в HTML это разделенная точкой с запятой строка. В Dash вы можете просто передать словарь.
- Ключи в style словаре немного различаются в написании относительно HTML. Вместо text-align мы пишем textAlign .
- Дочерние классы каждого элемента-тэга в Dash (класса) передаются в массиве через аргумент children .
Многоразовые компоненты
Продолжая, представим, что нам нужны некоторые элементы, которые будут меняться, например в зависимости от входных данных пользователя нашего приложения. Для этого в Dash предусмотрены так называемые reusable components . Рассмотрим их на примере таблицы, данные для которой будут загружаться из Pandas dataframe.
import dash import dash_core_components as dcc import dash_html_components as html import pandas as pd df = pd.read_csv( 'https://gist.githubusercontent.com/chriddyp/' 'c78bf172206ce24f77d6363a2d754b59/raw/' 'c353e8ef842413cae56ae3920b8fd78468aa4cb2/' 'usa-agricultural-exports-2011.csv') def generate_table(dataframe, max_rows=10): return html.Table( # Header [html.Tr([html.Th(col) for col in dataframe.columns])] + # Body [html.Tr([ html.Td(dataframe.iloc[i][col]) for col in dataframe.columns ]) for i in range(min(len(dataframe), max_rows))] ) external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div(children=[ html.H4(children='US Agriculture Exports (2011)'), generate_table(df) ]) if __name__ == '__main__': app.run_server(debug=True)
Немного о таблицах
Давайте вспомним что из себя представляет таблица в HTML.
HTML таблица определяется тэгом table.
Каждая строка таблица определяется тэгом tr. Хедер таблица определяется тэгом th. A ячейки таблицы заполняются с помощью тэга td.
Получается такая структура:
Firstname Lastname Age Jill Smith 50 Eve Jackson 94 John Doe 80
Компоненты ядра (Основные компоненты)
Как мы уже сказали ранее, dash_core_components включает в себя высокоуровнвые элементы. Такие, как: выпадающее меню, графики и прочее.
Вы можете ознакомиться с визуальной стороной этих элементов, каждый из которых сопровождается кодом (очень удобно, вселенский респект разрабочикам из Plot.ly) здесь.
Для того, чтобы разработчик, а именно Вы, могли в коде различать все элементы, принято для каждого компонента ядра писать лейбл. Это что-то типа названия нашего элемента. Это не обязательно, но просто облегчит отладку. А пользователю даст возможность быстрее разобраться в вашем интерфейсе. Далее вы поймете о чем я.
Давайте рассмотрим следующий код:
import dash import dash_core_components as dcc import dash_html_components as html external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div([ html.Label('Dropdown'), dcc.Dropdown( options=[ , , ], value='MTL' ), html.Label('Multi-Select Dropdown'), dcc.Dropdown( options=[ , , ], value=['MTL', 'SF'], multi=True ), html.Label('Radio Items'), dcc.RadioItems( options=[ , , ], value='MTL' ), html.Label('Checkboxes'), dcc.Checklist( options=[ , , ], values=['MTL', 'SF'] ), html.Label('Text Input'), dcc.Input(value='MTL', type='text'), html.Label('Slider'), dcc.Slider( min=0, max=9, marks='.format(i) if i == 1 else str(i) for i in range(1, 6)>, value=5, ), ], style=) if __name__ == '__main__': app.run_server(debug=True)
Тут мы видим, что мы создали как обычно один общий Div блок, в котором содержатся наши различные компоненты ядра. Выглядит это как-то так:
Остались вопросы?
Разработчики подготовили очень подробную документацию, прочитать вы ее можете типичной Python командой для каждого класса:
Summary
Ранее нами изученый layout описывает то, как выглядит наше приложение. По сути он содержит древовидную иерархию HTML тэгов и высокоуровневых элементов ядра Dash, которые содержатся в dash_core_components .
В следующей части мы изучим то, как сделать нашу страничку интерактивной. Если вам понравился данный туториал, ставьте плюсик и подписывайтесь на меня.
* Здесь скоро будет ссылка на следующую часть *
html.Div
Our recommended IDE for writing Dash apps is Dash Enterprise’s
Data Science Workspaces,
which has typeahead support for Dash Component Properties.
Find out if your company is using
Dash Enterprise.
children (list of or a singular dash component, string or number; optional):
The children of this component.
id (string; optional):
The ID of this component, used to identify dash components in
callbacks. The ID needs to be unique across all of the components in
an app.
n_clicks (number; default 0 ):
An integer that represents the number of times that this element has
been clicked on.
n_clicks_timestamp (number; default -1 ):
An integer that represents the time (in ms since 1970) at which
n_clicks changed. This can be used to tell which button was changed
most recently.
disable_n_clicks (boolean; optional):
When True, this will disable the n_clicks prop. Use this to remove
event listeners that may interfere with screen readers.
key (string; optional):
A unique identifier for the component, used to improve performance by
React.js while rendering components See
https://reactjs.org/docs/lists-and-keys.html for more info.
accessKey (string; optional):
Keyboard shortcut to activate or add focus to the element.
className (string; optional):
Often used with CSS to style elements with common properties.
contentEditable (string; optional):
Indicates whether the element’s content is editable.
dir (string; optional):
Defines the text direction. Allowed values are ltr (Left-To-Right) or
rtl (Right-To-Left).
draggable (string; optional):
Defines whether the element can be dragged.
hidden (a value equal to: ‘hidden’ or ‘HIDDEN’ | boolean; optional):
Prevents rendering of given element, while keeping child elements,
e.g. script elements, active.
lang (string; optional):
Defines the language used in the element.
role (string; optional):
Defines an explicit role for an element for use by assistive
technologies.
spellCheck (string; optional):
Indicates whether spell checking is allowed for the element.
style (dict; optional):
Defines CSS styles which will override styles previously set.
tabIndex (string; optional):
Overrides the browser’s default tab order and follows the one
specified instead.
title (string; optional):
Text to be displayed in a tooltip when hovering over the element.
loading_state (dict; optional):
Object that holds the loading state object coming from dash-renderer.
loading_state is a dict with keys:
- component_name (string; optional):
Holds the name of the component that is loading. - is_loading (boolean; optional):
Determines if the component is loading or not. - prop_name (string; optional):
Holds which property is loading.