2017-05-30 49 views
5

我使用Flask在网页上公开HTML文件的本地目录。使用相对href链接生成递归站点地图

我也在使用jinja2在我的主要终端的左手div中生成站点地图。

我是无法正确指定我的子文件夹的端点的URL。

正如以下代码所述,我将如何动态构建/docs(即/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> 

文件夹结构,例如:

demo structure

如何它看起来整体显示的file1.html内容: sitemap view

+1

您是否尝试过构建包含所有路径名称的树:https://stackoverflow.com/questions/10961378/how-to-generate-an-html-directory-list-using-python? – jbndlr

+0

@jbndlr这正是我最初看到的帖子。这就是我结束的地方。幸运的是,我找到了解决我遇到的问题的解决方案。谢谢。 –

回答

5

所以我想出了一个解决我自己问题的令人满意的方式。

我设法得到这个非常实用的结果: Flask serving Docs demo

请注意,我的模板仅适用于具有.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> 

你可以参考王刷新的回答为我在template.html文件已经更改为正确的,使这项工作进行了分析。

这里是demo_app.py脚本,通过瓶用于我的文档HTML文件:在demo_app.py因为问我原来的问题

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) 

最显着的变化如下:

  • 初始化app后,我使用app.static_folder设置DOCS_ROOT;
  • 在函数send_docs()中,我将send_from_directory()directory参数更改为使用DOCS_ROOT;
  • 里面的make_tree(),该for循环else块里面,我说:

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

    这一切确实是采取name绝对路径,删除哪些匹配DOCS_ROOT,只留下相对路径(和然后将\\替换为/),从而产生从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; 
} 
2

随着烧瓶中,我使用下面的

建一个网站地图
from flask import url_for 

def get_flask_resources(): 
    verbs = ["POST","GET","PUT","DELETE"] 

    resources = {} 
    for rule in app.url_map.iter_rules(): 
     if has_no_empty_params(rule): 
      resource = url_for(rule.endpoint, **(rule.defaults or {})) 
      if resource not in resources: 
       resources[resource] = {} 
      for verb in verbs: 
       if verb in rule.methods: 
        resources[resource][verb] = { 
         'function':rule.endpoint, 
         'docs':app.view_functions[rule.endpoint].__doc__ 
        } 
     else: 
      resource = rule.rule 
      if resource not in resources: 
       resources[resource] = {} 
      for verb in verbs: 
       if verb in rule.methods: 
        resources[resource][verb] = { 
         'function':rule.endpoint, 
         'docs':app.view_functions[rule.endpoint].__doc__ 
        } 

    return resources 

这个函数返回一个字典是这样

{ 
    "/endpoint1": { 
    "GET": { 
     "docs": "", 
     "function": "endpoint1" 
    } 
    }, 
    "/endpoint2": { 
    "GET": { 
     "docs": "", 
     "function": "endpoint2" 
    } 
    }, 
    "/endpoint1/something": { 
    "POST": { 
     "docs": "", 
     "function": "endpoint1_something" 
    } 
    }, 
} 

我有一个端点返回此数据,然后格式化它的前端。字典键是您想要在链接中使用的URI。

这的确假定您将为每个HTML文档设置烧瓶路线,但情况可能并非如此。

使用它的一个好处是,如果你添加更多的HTML文档/烧瓶路线,它是动态的。

+0

这很好,但是,正如你所猜测的那样,这不是我要找的。感谢分享! –

3

要添加到@ HEADLESS_0NE的溶液:

他在for loop增加了几个if语句,就像这样:

 {%- 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 %} 

->一切都在html被改变,我找不到他在pythoncss,但短期加什么:

  • if检查,如果有一个在item.name一个.html
  • item.name上拆分,因此/被删除。
  • 如果item.name中没有.html,则表示else声明。

这基本上以正确的格式添加ul's和li's。

有关更详细的解释,我希望HEADLESS_0NE可以向我们提供更多信息,他可能在python脚本中更改了它。

+0

感谢您花时间进一步解释我对Jinja模板文件所做的更改。我的示例文件没有版本,所以我会尽我所能。 –

+0

@ HEADLESS_0NE没问题:)我尽我所能解释了它的更多细节!感谢您对帖子的更新和完美的解决方法;) –

+0

我刚刚更新了它! –