2017-05-30 41 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

我剛剛更新了它! –