使用相对href链接生成递归站点地图

HEA*_*0NE 5 python jinja2

我正在使用Flask在网页上公开HTML文件的本地目录.

我也使用a jinja2div我的主端点的左侧生成站点地图.

无法正确指定子文件夹端点的URL.

如下面的代码所述,我将如何从/docs(ie /docs/folder1/subfolder1/SubFolder1Page.html)动态构建相对链接?我目前设置值的方式href显然不起作用.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Docs Demo</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
    <div id="container">
        <div class="left_frame">
            <h1>{{ tree.name }}</h1>
            <ul>
            {%- for item in tree.children recursive %}
                <!-- How would I build a relative link from /docs/ i.e. /docs/folder1/subfolder1/SubFolder1Page.html -->
                <li><a href="docs/{{ item.name }}" target="iframe1">{{ item.name }}
                {%- if item.children -%}
                    <ul>{{ loop(item.children) }}</ul>
                {%- endif %}</a></li>
            {%- endfor %}
            </ul>
        </div>
        <div class="right_frame">
            <iframe name="iframe1"></iframe>
        </div>
    </div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

文件夹结构示例:

演示结构

它如何整体显示以下内容file1.html: 站点地图视图

HEA*_*0NE 5

所以我找到了解决自己问题的令人满意的方法.

我设法得到了这个非常实用的结果: Flask提供Docs演示

请注意,我的模板仅适用于具有.html扩展名的文件,但可以轻松增强以支持其他文件扩展名.

这是我的最终templates\template.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Docs Demo</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
    <div id="container">
        <div class="left_frame">
            <h1>{{ tree.name }}</h1>
            <ul>
            {%- for item in tree.children recursive %}
                {% if '.html' in item.name %}
                    <li><a href="docs/{{ item.name }}" target="iframe1">
                    {{ item.name.split('/')[-1:][0] }}
                    {%- if item.children -%}
                        <ul>{{ loop(item.children) }}</ul>
                    {%- endif %}</a></li>
                {% else %}
                    <li>{{ item.name }}
                    {%- if item.children -%}
                        <ul>{{ loop(item.children) }}</ul>
                    {%- endif %}</li>
                {% endif %}
            {%- endfor %}
            </ul>
        </div>
        <div class="right_frame">
            <iframe name="iframe1"></iframe>
        </div>
    </div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

您可以参考King Reload的答案,分析我在template.html文件中更改的内容,以使其正常工作.

这是demo_app.py通过Flask提供我的文档HTML文件的脚本:

import threading
import os
import webbrowser
from flask import Flask, render_template, send_from_directory


app = Flask(__name__, static_folder='static')

ROOT = os.path.dirname(os.path.abspath(__file__))
DOCS_ROOT = os.path.join(app.static_folder, 'docs')


@app.route('/')
def docs_tree():
    return render_template('template.html', tree=make_tree(DOCS_ROOT))


@app.route('/docs/<path:filename>')
def send_docs(filename):
    return send_from_directory(directory=DOCS_ROOT, 'docs'), filename=filename)


def make_tree(path):
    tree = dict(name=os.path.basename(path), children=[])
    try:
        lst = os.listdir(path)
    except OSError:
        pass  # ignore errors
    else:
        for name in lst:
            fn = os.path.join(path, name)
            if os.path.isdir(fn):
                tree['children'].append(make_tree(fn))
            else:
                np = os.path.join(path.replace(DOCS_ROOT, ''), name).replace('\\', '/')
                if np.startswith('/'):
                    np = np[1:]
                tree['children'].append(dict(name=np))
    return tree

if __name__ == '__main__':
    host = 'localhost'
    port = '8888'
    url = 'http://{h}:{p}'.format(h=host, p=port)
    threading.Timer(3, lambda: webbrowser.open(url)).start()
    app.run(host=host, port=port, debug=False)
Run Code Online (Sandbox Code Playgroud)

demo_app.py自问我原来的问题以来,最值得注意的变化如下:

  • 初始化后app,我设置DOCS_ROOT使用app.static_folder;
  • 在函数中send_docs(),我改变了使用send_from_directory()directory参数DOCS_ROOT;
  • 在循环块的make_tree()内部,我添加了:elsefor

    np = os.path.join(path.replace(DOCS_ROOT, ''), name).replace('\\', '/')
    if np.startswith('/'):
        np = np[1:]
    
    Run Code Online (Sandbox Code Playgroud)

    所有这一切都是采取绝对路径name,删除匹配的东西DOCS_ROOT,只留下相对路径(然后替换\\for /),从而产生一个简单的相对路径static/docs.如果相对路径以开始/,我将其删除(因为有一个尾随/docstemplate.html.


对于任何对static\styles.css我使用的简单样式表()感兴趣的人(以及一些更新的增强功能):

html {
    min-height:100%;
    position:relative;
}

body {
    overflow:hidden;
}

.container {
    width:100%;
    overflow:auto;
}

.left_frame {
    float:left;
    background:#E8F1F5;
    width:25%;
    height:100vh;
}

.right_frame {
    float:right;
    background:#FAFAFA;
    width:75%;
    height:100vh;
}

.right_frame iframe {
    display:block;
    width:100%;
    height:100%;
    border:none;
}
Run Code Online (Sandbox Code Playgroud)