How to save a panel to html with plotly backend?

Hello guys,

I’m creating a panel dashboard with plotly graphs and I’m trying to save in html, but the graphs aren’t appearing.

Does someone know what is happening? When I’m using bokeh backend the graphs appeared beautifully in the html output.

The command: panel serve job.py
Command to save the panel: report_panel.save( filename=f"download_reports/panel.html", resources=CDN, )
Output:

You are generating standalone HTML/JS output, but trying to use real Python
callbacks (i.e. with on_change or on_event). This combination cannot work.
Only JavaScript callbacks may be used with standalone output. For more
information on JavaScript callbacks with Bokeh, see:
https://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html
Alternatively, to use real Python callbacks, a Bokeh server application may
be used. For more information on building and running Bokeh applications, see:
Bokeh server — Bokeh 3.3.2 Documentation

Welcome ! If you can share some code someone can take a look in the problem. However, as the output error is indicating, when you save your plots like an html file, you can not have python callbacks, only javascript callback . See the bottom explanation in https://panel.holoviz.org/user_guide/Deploy_and_Export.html

If you share some code, it is easier that somebody can look what the problem is :slight_smile: !

1 Like

Hello! Thanks :slight_smile:

I can’t share the whole code, but I can try to explain what I’m trying to do (I’m not a native english person, sorry for the mistakes and I hope you can understand)

First, I create two panels (two param classes). The first panel has two buttons (one button to update the second panel, other button to download the second panel) and the second panel contains the plotly graphs (the main content). I did that, because I didn’t want the buttons appeared in the exported html (with plotly graphs).

This is one piece of the first:

# Update button, this button update the second panel content
@param.depends("action")
def call_report(self):
    # This values are from a ObjectSelector
    if len(self.param["insertion_orders"].objects) == 1:
        self.insertion_orders = self.param["insertion_orders"].objects[0]

    self.Report.insertion_order = self.insertion_orders
    self.Report.campaign_name = self.campaigns
    self.Report.atd_details_filter = atd_details[
        atd_details.insertion_order_number == self.insertion_orders
    ]
    
    # Second panel content
    self.report_panel = self.Report.view()
    
    # This return is put in a pn.Row() function
    return self.report_panel

# Download button, this button export the second panel to html
@param.depends("download")
def call_download(self):
    if self.report_panel:
        self.report_panel.save(
            filename=f"download_reports/PI_{self.insertion_orders}.html",
            resources=CDN,
            embed=True,
        )
        return pn.pane.Markdown("Download success...")
    else:
        return pn.pane.Markdown("There's any report to download!")

Second, I run the code with panel serve main.py and the plotly graphs appeared perfectly, but when I try to save the output in a HTML file, the graphs doesn’t appeared :frowning: I tested with bokeh backend and the output saved perfectly. It’s the same function, I just change the backend!

A example graph with plolty:

def _imps_device(self):
    fig = go.Figure(
        data=[
            go.Pie(
                labels=self.device_type_metrics.device_type,
                values=self.device_type_metrics.imps.values,
            )
        ]
    )
    fig.update_layout(
        width=350,
        height=250,
        margin=dict(l=10, r=10, t=10, b=10, pad=2),
    )
    return pn.Column(
        pn.Row(pn.pane.Markdown("##Device Impressions")),
        pn.Row(
            pn.pane.Plotly(fig, config={"responsive": True}), css_classes=["center"]
        ),
    )

A example graph with bokeh:

def _imps_device(self):
    fig = self.device_type_metrics.rename(
        columns={"imps": "Impressions", "device_type": "Device"}
    ).plot_bokeh.pie(
        y="Impressions",
        x="Device",
        show_figure=False,
        figsize=(450, 350),
    )
    return pn.Column(
        pn.Row(pn.pane.Markdown("##Device Impressions")),
        pn.Row(pn.pane.Bokeh(fig), css_classes=["center"]),
    )

Is it clearer now?

1 Like

Hi @naanadr

I’ve tried it out but cannot get it working either. I’ve filed a bug report https://github.com/holoviz/panel/issues/1844.

Could you take a look at the bug report and add any comments you might have? Thanks.

1 Like

Thanks a lot!! I don’t have any comments to add, you summarized it very well :heart:

I’ll follow the issue now. If you need ping me, my github is @naanadr too .

1 Like