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

MkDocs Material中自定义Jinja Pandas过滤器异常及页面元数据调用问题求助

MkDocs Material中自定义Jinja Pandas过滤器异常及页面元数据调用问题求助

我正在用MkDocs的Material主题搭建站点,还添加了下面这个自定义过滤器:

import pandas
def csv_to_html(csv_path):
    return pandas.read_csv(csv_path).to_html()

我想根据MD文档的元数据找到对应的CSV文件,我的文档doc_12345.md内容如下:

---
title: myDocument
doc_number: doc_12345
---

我要解析的是doc_12345.csv这个文件,但Jinja过滤器的表现太不稳定了,我遇到了几个不同的问题:

第一个问题

过滤器好像只有用管道符(|)的时候才有效,下面这种写法会失败:

{{ csv_to_html("data/doc_12345.csv") }}

报错信息:

jinja2.exceptions.UndefinedError: 'csv_to_html' is undefined

但下面这种写法就正常:

{{ "data/doc_12345.csv" | csv_to_html }}

第二个问题

页面元数据的访问情况时好时坏。我参考了官方文档里的单页面元数据用法,用page.meta.doc_number来访问这个属性。单独引用的时候是正常的,比如:

{{ page.meta }}
# { 'title': 'myDocument', 'doc_number': 'doc_12345' }
{{ page.meta.doc_number }}
# doc_12345

但拼接字符串的时候就不行了:

{{ "data/" + page.meta.doc_number + ".csv" }}

报错信息:

jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'doc_number'

奇怪的是,如果用default()过滤器的话,又能找到doc_number属性了:

{{ "data/" + (page.meta.doc_number | default("random text")) + ".csv" }}
# data/doc_12345.csv

为什么传给过滤器的时候能找到,直接拼接就不行呢?

第三个问题

把拼接好的路径传给csv_to_html过滤器后,doc_number又不见了:

{{ "data/" + (page.meta.doc_number | default("random text")) + ".csv" | csv_to_html }}

报错信息:

FileNotFoundError: [Errno 2] No such file or directory: 'data/.csv'

我还试着把路径存成变量:

{% set csv_path = "data/" + (page.meta.doc_number | default("random text")) + ".csv" %}
{{ csv_path }}
# data/doc_12345.csv
{{ csv_path | csv_to_html }}
# FileNotFoundError: [Errno 2] No such file or directory: 'data/.csv'

更诡异的是,如果我修改csv_to_html让它直接返回输入的路径,结果就正常:

import pandas
def csv_to_html(csv_path):
    return csv_path
{{ csv_path | csv_to_html }}
# data/doc_12345.csv

也就是说,csv_path这个字符串在传给pandas.read_csv()之前都是正常的,但只要是用page.meta.doc_number拼接出来的路径,到了pandas那里就出问题。如果直接传字符串字面量"data/doc_12345.csv"给csv_to_html,就能正常把CSV转成HTML。

这完全说不通啊,到底是怎么回事?


补充最小可复现示例

mkdocs.yml

theme:
  name: material
  custom_dir: templates
plugins:
  - mkdocs-simple-hooks:
      hooks:
        on_env: "modules.hooks:on_env"

modules/hooks.py

import pandas

def csv_to_html(csv_path):
    return pandas.read_csv(csv_path).to_html(index=False)

def on_env(env, config, **kwargs):
    # 添加过滤器
    env.filters['csv_to_html'] = csv_to_html

data/doc_12345.csv

ColumnA,ColumnB,ColumnC
ValueA,ValueB,ValueC

docs/doc_12345.md

---
title: myDocument
doc_number: doc_12345
---
# Hello world

templates/main.html

{% extends "base.html" %}
{% block content %}
{{ ("data/" + page.meta.doc_number + ".csv") | csv_to_html }}
{{ page.content }}
{% endblock %}

备注:内容来源于stack exchange,提问作者jeremywat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:10:27