Python и Headless: как создавать интерактивные, адаптируемые и доступные отчеты

В этой статье я покажу вам, как извлекать данные из автономной CMS и создавать отчет о типах контента с помощью фреймворка Python: Dash.

Видеть значит верить

Я визуальный ученик. Я очень ценю, когда график или диаграмма сопровождают данные, или когда наглядное пособие доходит до «сути» в презентации. Не все так сильно любят диаграммы, как я, но визуальное представление данных полезно для всех. Например, что легче понять в презентации:

эти числа рядом: 101 | 443 | 102 | 320 | 82

or

этот график:

Имея только список чисел с разделителями, вы не получите четкого представления о том, как значения сравниваются друг с другом. График делает различия и сходства более очевидными.

Допустим, вы новый менеджер или член маркетинговой команды, которая использует автономную CMS для создания контента. Знание того, какие типы контента создает команда, будет полезно для лучшего понимания их текущей контент-стратегии. Однако, когда вы смотрите на модели контента в автономной CMS, вы обычно встречаетесь с длинным списком имен и номеров:

Чтобы оценить типы контента в проекте, вам нужно просмотреть весь список типов контента и мысленно сравнить значения. Без наглядного пособия трудно сказать, какие темы преобладают в вашем проекте. Кроме того, после того как вы закончите анализ, вы не сможете легко поделиться своими выводами с другими членами вашей команды. Заставить их поверить в правильность вашего анализа намного проще с помощью визуального отчета.

Но что, если у вас нет времени или ресурсов для интеграции инструмента коммерческой отчетности в свой проект? К счастью, существуют фреймворки и библиотеки с открытым исходным кодом для создания приложений веб-аналитики, например Dash.

Что такое Dash?

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

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

Как создать отчет из безголовой CMS

Давайте создадим отчет о содержании, используя Kentico Kontent headless CMS, Kontent Python SDK с открытым исходным кодом и Dash.

В нашем примере сценария мы создадим три отчета о веб-сайте кофейни и объединим их в отчет с вкладками.

В нашем отчете мы хотим показать:

  • какой тип контента существует в проекте
  • аудитории, на которые ориентированы наши статьи
  • временная шкала, показывающая, когда они были опубликованы.

Эти отчеты дадут нам больше информации о стратегии «кто, что и когда» в отношении наших ранее опубликованных статей.

Настройка приложения

Во-первых, нам нужно установить Dash, наш SDK и зависимости. Я рекомендую делать это в виртуальной среде. В терминале запустите:

  1. pip install dash
  2. pip install kontent_delivery
  3. pip install pandas

Кроме того, вы можете загрузить и установить этот requirements.txt с помощью pip install -r /path/to/requirements.txt.

К концу упражнения у нас будет файловая структура, которая будет выглядеть так:

kontent-dash-blog (root)/
    reports/
        article_timeline.py
        content_types.py
        personas.py
    report_dashboard.py
    requirements.txt

Инициализация Dash и контента

После того, как мы установили требования, нам необходимо:

  • настроить наше приложение Flask для запуска Dash
  • инициализировать наш клиент доставки Kontent SDK, используя наш Идентификатор проекта Kontent
  • настроить некоторые методы для создания наших трех отчетов

Мы сделаем это в файле под названием report_dashboard.py и создадим его в корне проекта:

import dash
import flask
from kontent_delivery.client import DeliveryClient
# report methods
from reports.content_types import build_types_chart
from reports.personas import build_personas_pie
from reports.article_timeline import build_post_timeline
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
# dash
server = flask.Flask(__name__)
app = dash.Dash(server=server, external_stylesheets=external_stylesheets)
# kontent
client = DeliveryClient("your_Kontent_Project_ID")
# custom methods to create reports
bar = build_types_chart(client)
pie = build_personas_pie(client)
timeline = build_post_timeline(client)

Отчет 1: гистограмма, показывающая типы контента

На этой диаграмме мы вызовем Kontent API и посчитаем, сколько существует типов контента данного типа. Мы создадим файл content_types.py в каталоге reports:

import plotly.express as px
def build_types_chart(client):
    type_response = client.get_content_types()
    item_response = client.get_content_items()
    types = {}
    # add Kontent type counts to a dictionary
    for content_type in type_response.types:
        types[content_type.codename] = 0
    # increment content type count per item of respective type
    for item in item_response.items:
        types[item.content_type] += 1 
    data = {"content types":types.keys(), "count": types.values()}
    fig = px.bar(data, x="content types", y="count")
    return fig

В методе build_types_chart мы создаем пары "ключ-значение" из кодового имени наших типов контента и подсчета количества опубликованных элементов этого типа. С этими данными мы используем Plotly Express для создания и возврата гистограммы в наше приложение Dash.

Отчет 2: круговая диаграмма, показывающая персонажей статей

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

Создадим файл personas.py в каталоге reports:

from kontent_delivery.builders.filter_builder import Filter
import plotly.express as px
def build_personas_pie(client):
    # only return "article" content items
    item_response = client.get_content_items(
        Filter("system.type", "[eq]", "article")
    )
    # get the taxonomy group that articles use
    personas_response = client.get_taxonomy("personas")
    chart_personas = {}
    # identify personas to be counted
    def get_taxonomy_terms(terms):
        for persona in terms:
            chart_personas[persona.name] = 0
            if persona.terms:
                get_taxonomy_terms(persona.terms)

    get_taxonomy_terms(personas_response.terms)
    # increment persona count per item
    for item in item_response.items:
        for persona in item.elements.personas.value:
            chart_personas[persona.name] += 1 
    data = {"personas":chart_personas.keys(), "count": chart_personas.values()}
    fig = px.pie(data, names="personas", values="count",
                title='Assigned article personas')
    return fig

В методе build_personas_pie мы извлекаем все элементы содержимого нашей статьи. Затем мы создаем пары «ключ-значение» из имени терминов таксономии, которые существуют в нашей таксономической группе «Персонажи», и подсчета количества элементов, помеченных определенным термином. С этими данными мы используем Plotly Express для создания и возврата круговой диаграммы в наше приложение Dash.

Отчет 3: временная шкала с указанием даты публикации

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

Создадим файл article_timeline.py в каталоге reports:

from kontent_delivery.builders.filter_builder import Filter
import pandas as pd
import plotly.express as px
def build_post_timeline(client):
    # only return "article" content items
    item_response = client.get_content_items(
        Filter("system.type", "[eq]", "article")
    )
    # setup two arrays for Plotly scatter
    chart_items = []
    chart_post_date = []
    # populate arrays with respective item name and post date
    for item in item_response.items:
        chart_items.append(item.name)
        chart_post_date.append(item.elements.post_date.value)
    df = pd.DataFrame(dict(item=chart_items, post_date=chart_post_date))
    # use column names of df for the different parameters x, y, ...
    fig = px.scatter(df, x="post_date", y="item",
                    title="Article post timeline",
                    labels={"Post Date":"Date item posted"} # customize axis label
                    )
    return fig

Как и другие методы, мы получаем элементы статьи из Kontent, но в этом примере мы делаем дополнительный шаг, чтобы преобразовать два массива в словарь и передать их в pandas DataFrame. Это сделано только для соответствия базовому примеру точечной диаграммы в документации Plotly.

Свяжите все вместе в отчете с вкладками с Dash

Пришло время собрать все наглядные пособия в одном отчете и добавить интерактивности с помощью Dash. Мы создали файл report_dashboard.py ранее, чтобы добавить клиент Kontent и наши методы построения диаграмм, а теперь мы добавим макет с некоторыми интерактивными компонентами:

# ... other imports from before
# add these for components:
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
# dash
server = flask.Flask(__name__)
app = dash.Dash(server=server, external_stylesheets=external_stylesheets)
# kontent
client = DeliveryClient(config.project_id, options=config.delivery_options)
bar = build_types_chart(client)
pie = build_personas_pie(client)
timeline = build_post_timeline(client)
# -- end of "Dash and Kontent Initialization" code --
# -- start of "Tying it all together..." code --
# adding the dash layout
app.layout = html.Div([
    # dash tabs component that wraps individual tabs
    dcc.Tabs(id='tabs-example', value='tab-1', children=[
        dcc.Tab(label='Content Types', value='tab-1'),
        dcc.Tab(label='Article Personas', value='tab-2'),
        dcc.Tab(label='Article Post Timeline', value='tab-3'),
    ]),
    # div used as a canvas to show reports
    html.Div(id='tabs-example-content')
])
# onclick events that call our chart building methods
@app.callback(Output('tabs-example-content', 'children'),
              Input('tabs-example', 'value'))
def render_content(tab):
    if tab == 'tab-1':
        return html.Div([
            dcc.Graph(figure=bar)
        ])
    elif tab == 'tab-2':
        return html.Div([
             dcc.Graph(figure=pie)
        ])
    elif tab == 'tab-3':
        return html.Div([
             dcc.Graph(figure=timeline)
        ])
# run the application when report_dashboard.py is called
if __name__ == '__main__':
    app.run_server(debug=True)

В окончательном файле кода нашего отчета мы используем основные HTML-компоненты Dash для создания простого макета с двумя блоками. Первый div содержит компоненты Dash Tab, которые мы используем для переключения между графиками, а второй div действует как холст для отображения сгенерированных нами графиков.

Следуя макету, мы используем обратные вызовы Dash для создания другого графика в зависимости от того, на какой вкладке мы нажимаем. Более подробную информацию об основных компонентах Dash, включая График и Вкладки, можно найти в документации Dash здесь.

На этом этапе вы можете запустить report_dashboard.py в своем терминале и посмотреть, как Dash запускает локальный сервер для вашего недавно созданного приложения для создания отчетов. Пройдите по ссылке в терминале, и ВОЙЛА! Вы бесплатно создали свой собственный интерактивный настраиваемый отчет.

Вы можете ознакомиться с живым размещенным примером или полным исходным кодом на GitHub.

Заключение

В этой статье мы обсудили, что такое Dash, и как вы можете использовать его для создания интерактивных отчетов на основе данных вашей автономной CMS. Теперь вы знаете, что обладая небольшими знаниями Python и фреймворком с открытым исходным кодом, таким как Dash, вы не должны упускать возможность получать отчеты CMS без заголовка.

Хотите больше образцов Dash и headless? Оцените это приложение Dash + Kontent для создания модульных графиков контента.

У вас возникли проблемы с образцами из статьи? Свяжитесь с нами в нашем Discord.

Больше контента на plainenglish.io