4 минут чтения
13 августа 2020 г.
Создаём дашборд на Bootstrap с нуля (Часть 1)
В прошлых материалах мы познакомились с фреймворком Plotly Dash, научились строить scatter plots и визуализировать данные на карте. Сегодня мы попробуем объединить имеющиеся части в одном веб-приложении и расскажем как можно создать полноценный дашборд используя сетчатую структуру Bootstrap.
В этом нам поможет dash-bootstrap-components, эта библиотека позволяет строить дашборды по принципу “plug-and-play”, добавлять любые компоненты Bootstrap и стилизовать их используя грид-дизайн.
Подготовка макета
Перед созданием любого приложения, не только дашборда нам просто необходим план, черновой макет, следуя которому, мы бы видели общую картину и могли быстро внести корректировки в структуру. Для создания макета дашборда мы использовали приложение draw.io, этот инструмент позволяет быстро создавать диаграммы, графики, блок-схемы, формы и т.д. Наш дашборд будет построен по следующему макету:
Как и сам дашборд, шапка будет оформлена в главных цветах Untappd — белом и золотом. Ниже расположится раздел с пивоварнями, состоящий из scatter plot и панели с настройками. А в самом низу будет карта, показывающая средний рейтинг напитка по регионам России.
— application.py
— assets/
|— typography.css
|— header.css
|— custom-script.js
|— image.png
Импортируем нужные библиотеки и инициализируем приложение:
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
from get_ratio_scatter_plot import get_plot
from get_russian_map import get_map
from clickhouse_driver import Client
from dash.dependencies import Input, Output
standard_BS = dbc.themes.BOOTSTRAP
app = dash.Dash(__name__, external_stylesheets=[standard_BS])
Главные аргументы для app:
__name__ — для активации cтатических элементов из папки assets (картинки, CSS и JS файлы)
external_stylesheets — внешний CSS для стилизации дашборда, здесь мы используем стандартный BootstrapCDN, однако вы можете создать свой или воспользоваться одним из уже готовых стилей.
Включаем ещё несколько параметров для работы с локальными файлами и подключаемся к ClickHouse:
app.scripts.config.serve_locally = True
app.css.config.serve_locally = True
client = Client(host=»,
user=’default’,
password=»,
port=’9000′,
database=’default’)
Добавим палитру цветов:
colors = [‘#ffcc00’,
‘#f5f2e8’,
‘#f8f3e3’,
‘#ffffff’,
]
Верстка макета
Все элементы дашборда будут помещены в Bootstrap Контейнер, который находится в блоке <div>:
— app
|— div
|— container
|— logo&header
|— container
|— div
|— controls&scatter
|— map
app.layout = html.Div(
[
dbc.Container(
< шапка >
dbc.Container(
html.Div(
[
< основной код >
],
),
fluid=False, style={‘max-width’: ‘1300px’},
),
],
style={‘background-color’: colors[1], ‘font-family’: ‘Proxima Nova Bold’},
)
Здесь мы сразу задаем фиксированную ширину контейнера, цвет фона и стиль шрифта на странице, который берется из typography.css в папке assets. Стоит подробней остановится на первом элементе блока div, это и есть заголовок страницы, он включает в себя логотип Untappd:
logo = html.Img(src=app.get_asset_url(‘logo.png’),
style={‘width’: «128px», ‘height’: «128px»,
}, className=’inline-image’)
и главный заголовок:
header = html.H3(«Статистика российских пивоварен в Untappd», style={‘text-transform’: «uppercase»})
Чтобы расположить эти два элемента на одной строке мы воспользовались Bootstrap Формами:
logo_and_header = dbc.FormGroup(
[
logo,
html.Div(
[
header
],
className=»p-5″
)
],
className=’form-row’,
)
В блоке html.Div параметр ’p-5’ позволяет добавить отступы и вертикально выровнять заголовок, а ’form-row’ поставить logo и header в один ряд. На данном этапе шапка дашборда вылгядит следующим образом:
Нам осталось выровнять их по центру и добавить красок. Для этого создаем отдельный контейнер, который будет состоять из одного ряда. В параметре className указываем ’d-flex justify-content-center’, чтобы выровнять элементы контейнера по центру.
dbc.Container(
dbc.Row(
[
dbc.Col(
html.Div(
logo_and_header,
),
),
],
style={‘max-height’: ‘128px’,
‘color’: ‘white’,
}
),
className=’d-flex justify-content-center’,
style={‘max-width’: ‘100%’,
‘background-color’: colors[0]},
),
На данном этапе шапка дашборда готова:
Далее в следующий Bootstrap Контейнер добавим первый подзаголовок:
dbc.Container(
html.Div(
[
html.Br(),
html.H5(«Пивоварни», style={‘text-align’:’center’, ‘text-transform’: ‘uppercase’}),
html.Hr(), # разделительная линия
Сам дашборд будет состоять из Bootstrap Карт, это обеспечит структурированное расположение всех элементов, придаст каждому элементу четкие границы и сохранит white space. Давайте создадим один из элементов дашборда, панель с настройками:
slider_day_values = [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
slider_top_breweries_values = [5, 25, 50, 75, 100, 125, 150, 175, 200]
controls = dbc.Card(
[
dbc.CardBody(
[
dbc.FormGroup(
[
dbc.Label(«Временной период», style={‘text-align’: ‘center’, ‘font-size’: ‘100%’, ‘text-transform’: ‘uppercase’}),
dcc.Slider(
id=’slider-day’,
min=1,
max=100,
step=10,
value=100,
marks={i: i for i in slider_day_values}
),
], style={‘text-align’: ‘center’}
),
dbc.FormGroup(
[
dbc.Label(«Количество пивоварен», style={‘text-align’: ‘center’, ‘font-size’: ‘100%’, ‘text-transform’: ‘uppercase’}),
dcc.Slider(
id=’slider-top-breweries’,
min=5,
max=200,
step=5,
value=200,
marks={i: i for i in slider_top_breweries_values}
),
], style={‘text-align’: ‘center’}
),
],
)
],
style={‘height’: ‘32.7rem’, ‘background-color’: colors[3]}
)
Панель включает два слайдера для управления scatter plot, они располагаются друг под другом в Bootstrap формах. Мы добавили слайдеры в один блок — dbc.CardBody. остальные эдементы будут добавлены по такому же принципу, это позволяет поставить одинаковые отступы со всех сторон . По умолчанию слайдеры оформлены в голубом цвете, для того чтобы изменить их стиль, воспользуйтесь файлом sliders.css, находящемся в папке assets.
Добавляем панель управления и scatter plot следующим блоком:
dbc.Row(
[
dbc.Col(controls, width={«size»: 4,
«order»: ‘first’,
«offset»: 0},
),
dbc.Col(dbc.Card(
[
dbc.CardBody(
[
html.H6(«Отношение количества отзывов к средней оценке пивоварни»,
className=»card-title»,
style={‘text-transform’: ‘uppercase’}),
dcc.Graph(id=’ratio-scatter-plot’),
],
),
],
style={‘background-color’: colors[2], ‘text-align’:’center’}
),
md=8),
],
align=»start»,
justify=’center’,
),
html.Br(),
И в конце страницы расположим карту:
html.H5(«Заведения и регионы», style={‘text-align’:’center’, ‘text-transform’: ‘uppercase’,}),
html.Hr(), #разделительная линия
dbc.Row(
[
dbc.Col(
dbc.Card(
[
dbc.CardBody(
[
html.H6(«Средний рейтинг пива по регионам»,
className=»card-title»,
style={‘text-transform’: ‘uppercase’},
),
dcc.Graph(figure=get_map())
],
),
],
style={‘background-color’: colors[2], ‘text-align’: ‘center’}
),
md=12),
]
),
html.Br(),
Callback-функции в Dash
Callback-функции позволяют сделать элементы дашборда интерактивными, если меняется входной элемент (Input), то и выход (Output) тоже изменится.
@app.callback(
Output(‘ratio-scatter-plot’, ‘figure’),
[Input(‘slider-day’, ‘value’),
Input(‘slider-top-breweries’, ‘value’),
]
)
def get_scatter_plots(n_days=100, top_n=200):
if n_days == 100 and top_n == 200:
df = pd.read_csv(‘data/ratio_scatter_plot.csv’)
return get_plot(n_days, top_n, df)
else:
return get_plot(n_days, top_n)
Входные/ выходные (Input/Output) значения это, проще говоря, параметр value элемента с определенным id. Например, входное значение верхнего слайдера с id=’slider-day’, показывающего временной период по умолчанию 100. При изменении этого значения функция, обернутая в декоратор будет вызвана автоматически и output на графике обновится. Больше примеров представлено на сайте plotly.
Важный момент, чтобы scatter plot при загрузке страницы отображал данные нам нужно сперва считать их из сохраненного датафрейма в папке data (указать начальное состояние), иначе scatter plot будет пустым. В дальнейшем при изменении параметров слайдера данные будут загружаться из ClickHouse таблиц.
Далее добавим пару строк отвечающих за поднятие локального сервера и приложение готово к запуску:
application = app.server
if __name__ == ‘__main__’:
application.run(debug=True, port=8000)
Теперь осталось только загрузить его на AWS с помощью BeansTalk и наш дашборд на Bootstrap готов:
Это была первая часть нашего выпуска, в следующей мы добавим больше новых bootstrap компонентов, callback-ов и расскажем про стилизацию таблиц.
[ Рекомендации ]
Читайте также
[ Связаться ]
Давайте раскроем потенциал вашего бизнеса вместе
Заполните форму на бесплатную консультацию