Python

Часть 1, Часть 2

Это вторая статья из нашей серии об использовании Python-фреймворка Dash от Plotly в качестве основной платформы для работы с панелью индикаторов. Прежде чем углубиться в эту статью, вы можете ознакомиться с первой частью, в которой рассмотрен обзор макета и интерактивных функций Dash в общем виде.

Примечание: Во всех примерах кода, представленных далее, элементы html.Div находятся в html-элементах макета приложения (см. «Компоненты Dash»), в то время как другие функции (например, функции обратного вызова) определены отдельно.

Идеи для работы с панелью индикаторов на продвинутом уровне с использованием Dash (продолжение)

2) Управление и обратные вызовы

Динамическая панель индикаторов служит очень эффективным средством для решения ряда задач, которые помогают пользователю изменять и работать с входными данными для элементов панели индикаторов. Параметры входных данных могут выполнять множество действий в отношении графиков и таблиц. В частности они могут производить:

  • Сужение графиков для выбранного диапазона дат (DatePickerRange).
  • Фильтрацию строк таблиц в соответствии с определенными условиями.
  • Загрузку в приложение локальных файлов (изображения или CSV) в табличном виде.

В этом разделе мы подробно рассмотрим расширение функциональности элементов управления и обратных вызовов, а именно — изменение элементов ввода.

2.1) Использование элементов ввода для изменения элементов ввода более низкого порядка

Часто возникает необходимость в динамическом изменении параметров элементов ввода, например раскрывающегося списка, на основе другого связанного с ним элемента. Допустим, если у нас есть два поля ввода, Страны и Штаты, было бы предпочтительно, чтобы выбор штата динамически отражал выбранную страну. Основная идея состоит в том, чтобы избавить пользователя от необходимости запоминать допустимые комбинации входных параметров для содержимого панели индикаторов.

Ниже приведен пример кода вышеупомянутого сценария и демонстрация того, как его можно реализовать:

html.Div([
        	html.Label("Country :"),
        	dash_core_components.Dropdown(
            	id="country",
            	options=[{"label":c, "value":c} for c in sorted(['USA','Canada'])],
            	placeholder = "Select Country...",
            	value = 'Select'
        	),
    	], style={"display":"inline-block", "textAlign":"center", "width":"12%"}),

    	html.Div([
        	html.Label("State :"),
        	dash_core_components.Dropdown(
            	id="state",
            	options=[{"label":s, "value":s} for s in region_data['State'].values],
            	placeholder = "Select State..."
        	),
    	], style={"display":"inline-block", "textAlign":"center", "width":"12%"}),

@app.callback(
	dash.dependencies.Output(component_id='state', component_property='options'),
	[dash.dependencies.Input(component_id='country', component_property='value')]
)
def update_state_values(country_input):
	St = region_data[region_data['Country']==country_input]['State'].values
	return [{'label':i,'value':i} for i in St]

Вывод:

3) Организационные свойства

Создание многослойной архитектуры в этом разделе будет рассмотрено на примере использования вкладок и многостраничных приложений. Если необходимо отразить элементы интерфейса панели, отвечающие за выполнение различных целей, множественные вкладки и страницы обеспечат лучшую структуру приложения.

Примечание: посредством этой процедуры будут использоваться обратные вызовы для элементов, изначально отсутствующих в макете приложения (если на других страницах или вкладках присутствуют обратные вызовы). Dash здесь делает исключение, чтобы указать, что мы, возможно, делаем что-то не так. Чтобы игнорировать этот вопрос, сразу после инициализации приложения с помощью app = Dash.dash() установите:

App.config.suppress_callback_exceptions = True

3.1) Множественные вкладки

Корпоративная панель индикаторов должна предоставлять широкую перспективу для наблюдения за ключевыми показателями бизнес-процессов. Разработка функции быстрого переключения между вкладками в информационной панели предоставит больше свободы для разностороннего анализа метрик.

В последней версии библиотеки dash core components эта функциональность вкладок легко реализуется двумя способами: «Содержимое как обратный вызов» и «Содержимое как дочерние элементы вкладки». Первый позволяет вкладке служить входными данными для стиля или значений контейнера, тем самым изменяя свойства элемента (например, графика или таблицы), выступая в качестве некоторого параметра. В последнем можно продемонстрировать разную компоновку контейнеров для каждой выбранной вкладки. Дополнительную информацию о вкладках можно найти здесь .

Важно учитывать, что содержимое вкладки вычисляется заранее и целиком отправляется на панель индикаторов по сети. С этим могут возникнуть проблемы в случае, если у пользователя присутствуют большие сетевые запросы или интенсивные вычисления, работающие в бэкенде. Что касается обсуждений на форуме, существуют исследования, посвященные тому, как сделать так, чтобы содержимое в Dash загружалось «по запросу». Работа с табличными разделами по отдельности обеспечит большую плавность в работе браузера. Что касается дизайна, вкладки имеют различные параметры, которые можно изменить в соответствии с целями вашего приложения. Например, можно настроить вертикальное размещение вкладок на странице и, как упоминалось ранее, обеспечить функционирование обратного вызова или средства для отображения различных макетов.

html.Div(children=[
	dash_core_components.Tabs(
    	id="tabsID",
    	children=[
		dash_core_components.Tab(label='Time-wise Sales', 
					 children=[time_wise_layout ]),	
		dash_core_components.Tab(label='Region-wise Sales', 
					 children=[region_wise_layout]),
		dash_core_components.Tab(label='Category-wise Sales', 
					 children=[category_wise_layout]),
		],
    	value="Time-wise Sales" ## Определяет вкладку,которую открывать
	) 
])

Выше рассмотрен код, который создает три вкладки с переменными time_wise_layout, region_wise_layout и category_wise_layout. Предполагается, что последняя содержит HTML-макеты, которые должны отображаться под каждой вкладкой. Ниже приведен вывод для этого кода:

В показанном примере компонент tabs служит для объяснения «содержимого как дочерних элементов вкладок» и реализации, которая потребуется. По сути, атрибут dcc «Tabs» является портом отдельных страниц «Tab», где каждая вкладка может иметь разный макет. В случае выше макеты region_wise_layout и time_wise_layout присвоены вкладкам Time-wise Sales и Region-wise Sales, где первая представляет собой линейный график, а вторая таблицы. После проверки становится очевидным, что каждая из этих отдельных вкладок также может включать входные параметры (например, поле «Страна» в Region-wise Sales), эффективно демонстрируя, что эти вкладки не зависят друг от друга.

3.2) Создание многостраничного приложения

Структурирование многостраничного приложения применяется довольно часто, так как далеко не все функции панели индикаторов должны быть не связаны друг с другом по выполняемым действиям. Например, приложение бизнес-аналитики может иметь различные страницы, каждая из которых идентифицируется уникальным образом для конкретной команды компании (например, маркетинг, наука о данных), и нет необходимости объединять все эти основы в одностраничное приложение. Большая и беспорядочная панель инструментов может быть неинтуитивной и запутанной. Dash решает эту проблему за счет использования многостраничных приложений.

Основная идея этой функции заключается в том, что dash отображает веб-приложения как «одностраничные» приложения. Это означает, что приложение панели мониторинга не будет обновляться, если пользователь взаимодействует с несколькими различными URL-адресами в рамках одного веб-приложения, что делает процесс просмотра очень плавным и быстрым. Разделение многоцелевой панели мониторинга на более мелкие и четкие отдельные страницы, из которых единственной выполняемой страницей является та, на которой в данный момент находится пользователь, позволяет Dash оптимизировать производительность приложения и обеспечивает удобство использования.

html.Div([
    dash_core_components.Location(id="url"),
    html.Div([
        dash_core_components.Link('Performance', href="/Performance", style=tab_style),
        dash_core_components.Link('Marketing', href="/Marketing", style=tab_style),
        dash_core_components.Link('Finance', href="/Finance", style=tab_style)
    ]),
    html.Div(id='content-field-in-app-layout')
])

Приведенный выше фрагмент кода является простейшим примером построения элемента разделения с помощью URL. Функция Location представляет адресную строку на странице через свойство URL pathname. Впоследствии в функции Link указывается отображаемое имя ссылки (например, «A») и соответствующее расширение веб-приложения (например, «dash_example.com/A»). С этими двумя свойствами пользователю разрешено перемещаться по многостраничному приложению. В следующем примере показано, как использовать URL-адреса для отображения нескольких табличных страниц.

@app.callback(Output('content-field-in-app-layout', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):
    if pathname == "/Performance":
   	 return Perform_layout
    elif pathname == "/Marketing":
   	 return Marketing_layout
    elif pathname == "/Finance":
   	 return Finance_layout
    else:
   	 return Error_display_layout

Приведенный выше код создает три страницы с отдельными ссылками. Предполагается, что переменные Perform_layout, Marketing_layout и Finance_layout содержат HTML-макеты, которые должны отображаться при посещении соответствующей ссылки.

Вышеуказанный обратный вызов запускает возврат определенного макета (содержащего элементы dash по желанию пользователя) на основе пути URL. Проще говоря, если бы путь был /Performance, пользователь хотел бы, чтобы отображался Perform_layout. Эти макеты будут возвращены в поле html.Div в app_layout (в данном случае идентификатор поля content-field-in-app-layout), а затем будут выведены на дисплей. Вы также можете внести конкретные изменения в элементы стиля ссылки (например, расстояние между ссылками, цвет). Тщательный обзор CSS будет рассмотрен в третьей части нашей серии.

Для подтверждения вышеупомянутых моментов приведен следующий график. В нём демонстрируется многостраничное приложение, работающее с каждой страницей, идентифицируемой уникальным URL. Performance_layout отличается более высоким уровнем организации вкладок, рассмотренных в разделе «Множественные вкладки », что позволяет повысить модульность и построить большие панели индикаторов за счет развертывания структуры на более мелкие элементы.

На этом мы заканчиваем вторую часть нашей серии.

Читайте также:


Перевод статьи Drimik Roy: A Python Programmers’ Guide to Dashboarding — Part 2

Предыдущая статьяGitHub-репозитории, о которых должен знать каждый разработчик
Следующая статьяJMeter-тестирование динамической нагрузки Restful API