Могу ли я управлять встроенным CSS, созданным Bokeh (или полностью его удалить)?

Я создаю приборную панель на панели PyViz, которая, насколько я понимаю, использует боке под капотом. Его легко использовать, и я быстро получаю решение на 90%, но окончательный макет проще (для меня) просто сделать с помощью простого старого CSS (макет сетки или что-то в этом роде). Я могу прикрепить html-идентификаторы и классы к каждому виджету / графику / столбцу / строке и т. Д. Из Python, но я не нашел способа остановить боке от включения длинной строки встроенного CSS в каждый создаваемый им div. Я хочу, чтобы макет был отзывчивым, без жестко заданной ширины / высоты или чего-то подобного.

Я уже обслуживаю код панели из main.ipynb в каталоге с template/index.html, поэтому решение с использованием шаблонов совершенно нормально. Я не хочу создавать всю панель управления во многих разных корнях, которые добавляются в шаблон, если мне это не нужно, сгенерированный html из строк и столбцов отлично подходит для моих целей, если бы я мог просто удалить сгенерированные встроенные атрибуты css .

Я могу написать функцию Python, которая просматривает дерево виджетов панели / боке и изменяет виджеты, если это требуется. Я, конечно, также могу перемещаться по DOM в Javascript и удалять атрибуты стиля из div-ов по мере их создания, но это кажется менее элегантным, чем собирать вместе несколько !important css.

В сторону: кто-нибудь знает, как остановить боке от изменения атрибута заголовка html из Javascript или как установить заголовок с панели?

Пример панели инструментов:

Это минималистичная приборная панель без какого-либо нестандартного стиля. Он производит жестко запрограммированные ширину и высоту для каждого div (как видно из инспектора элементов Firefox devtools). Панель управления выровнена по левому краю и неэффективно использует пространство экрана (много белого пространства слева, гистограмма не охватывает ту же горизонтальную ширину, что и строка выше). Макет также не реагирует на изменение размера страницы.

import numpy
import pandas
import param
import panel
import holoviews
from IPython.display import display


panel.extension()
holoviews.extension('bokeh')

# Create syntetic dataset
N= 1000
age = numpy.random.gamma(10, 1.5, N)
defects = numpy.clip(numpy.random.chisquare(5, N) * age - 10, 0, 1e100).astype(int)
df = pandas.DataFrame({'age': age, 'defects': defects})
display(df.head(3))

# default sizing_mode
SM = 'stretch_width'


class DashboardDefinition(param.Parameterized):
    age = param.Range((0, 20), (0, None), softbounds=(0, 30))
    histogram = param.ObjectSelector('defects', ['defects', 'age'])

    def filter_data(self, table):
        return table.select(age=self.age)

    @param.depends('age')
    def make_scatter(self):
        scatter = holoviews.Points(df, ['age', 'defects'])
        selected = self.filter_data(scatter)
        return panel.panel(selected, sizing_mode=SM)

    @param.depends('age', 'histogram')
    def make_histogram(self):
        table = holoviews.Table(df, self.histogram)
        table = self.filter_data(table)
        frequencies, edges = numpy.histogram(table[self.histogram], 15)
        hist = holoviews.Histogram((frequencies, edges))
        return panel.panel(hist, sizing_mode=SM)

    def layout(self):
        return panel.Column(panel.Row(self.param,
                                      self.make_scatter,
                                      sizing_mode=SM),
                            self.make_histogram,
                            sizing_mode=SM)


dashboard = DashboardDefinition(name='Dashboard parameters')
dash_panel = dashboard.layout() 

# Define the dashboard
template = """
{% extends base %}

{% block title %}Hello world{% endblock %}

{% block contents %}
<h1>My dashboard</h1>
<p>This is my currently unstyled dashboard</p>
<br>
{{ embed(roots.dash1) }}
{% endblock %}
"""
tmpl = panel.Template(template)
tmpl.add_panel('dash1', dash_panel)
tmpl.servable()

# Uncomment to preview dashboard in jupyter notebook
#dash_panel

person Tormod Landet    schedule 07.06.2019    source источник


Ответы (1)


Я решил свою конкретную проблему, установив responsive=True в голографических обзорах (спасибо xavArtley в https://gitter.im/pyviz/pyviz за помощь в этой части). Из документов bokeh кажется, что этот параметр удален, но он есть в головных обзорах, и его использование позволяет встроенному CSS соответствовать тому, что я хочу.

Вы должны стилизовать элементы перед запуском javascript, иначе размеры будут неправильными, но вы можете многое сделать, поместив собственный CSS в преамбулу шаблона (postamble не будет работать, по крайней мере, в Firefox) .

Рабочий пример

Здесь контейнер вокруг приборной панели определяет размеры компонентов приборной панели, а не встроенный CSS (который устанавливается Javascript в соответствии с окружающим элементом div):

import numpy
import pandas
import param
import panel
import holoviews


panel.extension()
holoviews.extension('bokeh')

# Create syntetic dataset
N= 1000
age = numpy.random.gamma(10, 1.5, N)
defects = numpy.clip(numpy.random.chisquare(5, N) * age - 10, 0, 1e100).astype(int)
df = pandas.DataFrame({'age': age, 'defects': defects})


class DashboardDefinition(param.Parameterized):
    age = param.Range((0, 20), (0, None), softbounds=(0, 30))
    histogram = param.ObjectSelector('defects', ['defects', 'age'])

    def filter_data(self, table):
        return table.select(age=self.age)

    @param.depends('age')
    def make_scatter(self):
        scatter = holoviews.Points(df, ['age', 'defects'])
        selected = self.filter_data(scatter)
        hv_obj = selected.options(responsive=True, aspect=3)
        return panel.panel(hv_obj)

    @param.depends('age', 'histogram')
    def make_histogram(self):
        table = holoviews.Table(df, self.histogram)
        table = self.filter_data(table)
        frequencies, edges = numpy.histogram(table[self.histogram], 25)
        hist = holoviews.Histogram((frequencies, edges))
        hv_obj = hist.options(responsive=True, aspect=4)
        return panel.panel(hv_obj)

    def layout(self):
        return panel.Column(panel.Row(self.param,
                                      self.make_scatter,
                                      sizing_mode='stretch_width'),
                            self.make_histogram,
                            sizing_mode='stretch_width')


dashboard = DashboardDefinition(name='Dashboard parameters')
dash_panel = dashboard.layout() 

# Define the dashboard
template = """
{% extends base %}

{% block preamble %}
<style>
div#dashboard {
    width: 80%;
    margin: 0 auto;
}
</style>
{% endblock preamble %}

{% block contents %}
<div id="dashboard">
  <h1>My dashboard</h1>
  {{ embed(roots.dash1) }}
</div>
{% endblock contents %}
"""
tmpl = panel.Template(template)
tmpl.add_panel('dash1', dash_panel)
tmpl.servable(title="My page title")

# Uncomment to preview dashboard in jupyter notebook
#dash_panel
person Tormod Landet    schedule 07.06.2019