You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarto 1.2升级至1.3后panel-tabset与pandas.to_html()交互异常解决方法

Quarto 1.3 动态生成标签页的解决方案

问题根源

你之前的写法属于非官方支持的取巧方式:利用Quarto 1.2对动态输出的二级标题(##)的兼容逻辑,让panel-tabset自动将标题识别为标签页。但1.3版本修复了这个解析规则,动态输出的Markdown标题不再触发panel-tabset的标签拆分,所以所有内容都挤在了第一个标签里。

1.3版本的正确实现方式

要在1.3里动态生成panel-tabset标签页,需要直接输出Quarto官方定义的panel-tab块结构,让Quarto明确识别每个标签的边界。修改后的代码如下:

# | output: asis
import pandas as pd
import random
from IPython.display import display, Markdown

df = pd.DataFrame({
    "group": ["a"]*3 + ["b"]*3 + ["c"]*3,
    "value": [random.randint(1,10) for i in range(9)]
})

# 循环生成每个标签页的完整结构
for group in df["group"].drop_duplicates():
    # 起始标记:定义标签页标题
    display(Markdown(f"::: {{.panel-tab}}#{group}\n"))
    # 输出格式统一的Markdown表格
    display(Markdown(df[df["group"]==group].to_markdown()))
    # 结束标记
    display(Markdown("\n:::"))

外层保留原有的::: {.panel-tabset}容器即可,注意每个panel-tab块的起始和结束标记必须完整,Quarto才能正确解析出独立标签页。

替代方案

如果不想依赖Quarto的panel-tabset解析逻辑,还有两种可靠的替代方式:

方案一:直接输出Bootstrap Tab HTML结构

Quarto的HTML格式基于Bootstrap,直接写原生Bootstrap的tab组件,兼容性更强,不受Quarto版本影响:

# | output: asis
import pandas as pd
import random

df = pd.DataFrame({
    "group": ["a"]*3 + ["b"]*3 + ["c"]*3,
    "value": [random.randint(1,10) for i in range(9)]
})

# 生成Tab导航栏
tabs_html = """
<ul class="nav nav-tabs" id="groupTab" role="tablist">
"""
for idx, group in enumerate(df["group"].drop_duplicates()):
    active_status = "active" if idx == 0 else ""
    tabs_html += f'<li class="nav-item" role="presentation"><button class="nav-link {active_status}" id="{group}-tab" data-bs-toggle="tab" data-bs-target="#{group}" type="button" role="tab" aria-controls="{group}" aria-selected={"true" if idx==0 else "false"}>{group}</button></li>'
tabs_html += "</ul>"

# 生成Tab内容面板
content_html = '<div class="tab-content" id="groupTabContent">'
for idx, group in enumerate(df["group"].drop_duplicates()):
    active_status = "show active" if idx == 0 else ""
    content_html += f'<div class="tab-pane fade {active_status}" id="{group}" role="tabpanel" aria-labelledby="{group}-tab">'
    content_html += df[df["group"]==group].to_html(classes="table table-striped")
    content_html += "</div>"
content_html += "</div>"

# 输出完整HTML结构
print(tabs_html + content_html)

方案二:使用ipywidgets交互式标签页

适合需要更复杂交互的场景,需启用widget渲染:

# | output: asis
# | widget: true
import pandas as pd
import random
import ipywidgets as widgets
from IPython.display import display

df = pd.DataFrame({
    "group": ["a"]*3 + ["b"]*3 + ["c"]*3,
    "value": [random.randint(1,10) for i in range(9)]
})

# 创建每个标签的内容面板
tab_contents = []
tab_titles = []
for group in df["group"].drop_duplicates():
    tab_titles.append(group)
    # 用HTML组件渲染表格
    tab_content = widgets.HTML(df[df["group"]==group].to_html(classes="table table-striped"))
    tab_contents.append(tab_content)

# 创建Tab组件并设置标题
tab = widgets.Tab()
tab.children = tab_contents
for i, title in enumerate(tab_titles):
    tab.set_title(i, title)

# 显示交互式标签页
display(tab)

内容的提问来源于stack exchange,提问作者DataJack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:51:19