我正在使用Flask在网页上公开HTML文件的本地目录。
我还使用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>
文件夹结构示例:
答案 0 :(得分:5)
所以我找到了解决自己问题的令人满意的方法。
请注意,我的模板仅适用于扩展名为.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>
您可以参考 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)
自问我原来的问题后demo_app.py
中最显着的变化如下:
app
后,我使用DOCS_ROOT
设置app.static_folder
; send_docs()
中,我更改了send_from_directory()
的{{1}}参数以使用directory
; 在DOCS_ROOT
内部,在make_tree()
循环的else
块内,我添加了:
for
所有这一切都取np = os.path.join(path.replace(DOCS_ROOT, ''), name).replace('\\', '/')
if np.startswith('/'):
np = np[1:]
的绝对路径,删除与name
匹配的内容,只保留相对路径(然后替换DOCS_ROOT
\\
),导致/
的简单相对路径。如果相对路径以static/docs
开头,我会将其删除(因为/
中/
的结尾docs
。
对于我使用的简单样式表(template.html
)感兴趣的人(以及一些更新的增强功能):
static\styles.css
答案 1 :(得分:3)
添加到@ HEADLESS_0NE的解决方案:
他在if
中添加了一些for loop
语句,如下所示:
{%- 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
的所有内容,我无法找到他在python
或css
中添加的内容,但简而言之:
if
检查.html
中是否有item.name
。item.name
上的拆分,因此/
被移除。else
中没有.html
,则为item.name
声明。这基本上会以正确的格式添加ul
和li
。
有关更详细的解释,我希望HEADLESS_0NE能够向我们提供更多信息,了解他可能在python
脚本中发生的变化。
答案 2 :(得分: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文档/ Flask路由,它将是动态的。