10

我想要导航我的Flask应用程序的面包屑。一个选项可能是使用像bread.py这样的通用 Python 模块:

面包对象接受一个 url 字符串并授予对 url crumbs(部分)或 url 链接(每个 crumb 的 href 列表)的访问权限。

bread.py 从 url 路径生成面包屑,但我希望面包屑的元素是以前访问过的页面的标题和链接。

在 Flask 中,也许这可以使用装饰器或扩展@route装饰器来完成。

有没有办法让每次调用都route()将页面的标题和链接(在用 装饰的函数/类中定义@route)添加到面包屑?还有其他方法吗?为 Flask 实现的面包屑的任何示例?

4

2 回答 2

12

所以你是在“路径/历史”面包屑之后,而不是“位置”面包屑来使用维基百科文章中的术语?

如果您想访问用户访问链接的历史记录,那么您将不得不将它们保存在会话中。我已经尝试过创建一个装饰器来做到这一点。

breadcrumb.py

import functools
import collections

import flask

BreadCrumb = collections.namedtuple('BreadCrumb', ['path', 'title'])

def breadcrumb(view_title):
    def decorator(f):
        @functools.wraps(f)
        def decorated_function(*args, **kwargs):
            # Put title into flask.g so views have access and
            # don't need to repeat it
            flask.g.title = view_title
            # Also put previous breadcrumbs there, ready for view to use
            session_crumbs = flask.session.setdefault('crumbs', [])
            flask.g.breadcrumbs = []
            for path, title in session_crumbs:
                flask.g.breadcrumbs.append(BreadCrumb(path, title))

            # Call the view
            rv = f(*args, **kwargs)

            # Now add the request path and title for that view
            # to the list of crumbs we store in the session.
            flask.session.modified = True
            session_crumbs.append((flask.request.path, view_title))
            # Only keep most recent crumbs (number should be configurable)
            if len(session_crumbs) > 3:
                session_crumbs.pop(0)

            return rv
        return decorated_function
    return decorator

这是一个演示它的测试应用程序。请注意,我刚刚使用了 Flask 的内置客户端会话,您可能希望在生产中使用更安全的服务器端会话,例如Flask-KVsession

#!/usr/bin/env python
import flask
from breadcrumb import breadcrumb

app = flask.Flask(__name__)

@app.route('/')
@breadcrumb('The index page')
def index():
    return flask.render_template('page.html')

@app.route('/a')
@breadcrumb('Aardvark')
def pagea():
    return flask.render_template('page.html')

@app.route('/b')
@breadcrumb('Banana')
def pageb():
    return flask.render_template('page.html')

@app.route('/c')
@breadcrumb('Chimp')
def pagec():
    return flask.render_template('page.html')

@app.route('/d')
@breadcrumb('Donkey')
def paged():
    return flask.render_template('page.html')

if __name__ == '__main__':
    app.secret_key = '83cf5ca3-b1ee-41bb-b7a8-7a56c906b05f'
    app.debug = True
    app.run()

这是以下内容templates/page.html

<!DOCTYPE html>
<html>
    <head><title>{{ g.title }}</title></head>
    <body>
        <h1>{{ g.title }}</h1>
        <p>Breadcrumbs:
        {% for crumb in g.breadcrumbs %}
            <a href="{{ crumb.path }}">{{ crumb.title }}</a>
            {% if not loop.last %}&raquo;{% endif %}
        {% endfor %}
        </p>
        <p>What next?</p>
        <ul>
            <li><a href="/a">Aardvark</a>?</li>
            <li><a href="/b">Banana</a>?</li>
            <li><a href="/c">Chimp</a>?</li>
            <li><a href="/d">Donkey</a>?</li>
        </ul>
    </body>
</html>
于 2012-11-30T00:07:07.883 回答
0

我试图使用 breadcrumb.py ,但我需要检查:

  • 如果新项目“item = (flask.request.path, view title)”已经存在于会话碎片中,那么我将从索引中删除所有其他项目到最后,我这样做是为了避免在我的会话碎片中重复.

             flask.session.modified = True
             item = (flask.request.path, view_title)
             try:
                 if not item in session_crumbs:
                     session_crumbs.append(item)
                 else:
                     index = session_crumbs.index(item)
    
                     session_crumbs = session_crumbs[:index+1]
    
             except:
                 pass
    
             return rv
         return decorated_function
     return decorator
    
于 2021-01-26T12:33:51.797 回答