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
相关产品推荐
相关产品推荐

