2012-11-18 56 views
7

我想讓麪包屑導航我的Flask應用程序。一種選擇可能是使用一般的Python模塊一樣bread.py使用Flask在Python中實現麪包屑?

麪包對象接受一個URL字符串並授予訪問URL 屑(部分)或URL鏈接(HREF中的列表,每個麪包屑)。

bread.py從url路徑生成breadcrumb,但我希望breadcrumb的元素成爲先前訪問過的頁面的標題和鏈接。

在Flask中,也許這可以使用裝飾器或通過擴展裝飾器來完成。

有沒有辦法讓每個route()的調用都添加頁面的標題和鏈接(在用@route裝飾的函數/類中定義)到麪包屑?還有其他方法可以做到嗎?任何Flask實施的麪包屑的例子?

回答

10

所以你是在「路徑/歷史」麪包屑,而不是「位置」麪包屑使用術語從wikipedia article

如果你想訪問用戶的訪問過的鏈接歷史,那麼你將不得不將它們保存在一個會話中。我已經創建了一個裝飾器來做到這一點。

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> 
+0

這是真棒,但如果你正在嘗試做的「位置」基於食物殘渣呢?你能否爲此添加一個答案?我認爲這會容易得多。 – chrickso

+0

@chrisckso:我認爲基於位置的麪包屑是[bread.py](http://russell.ballestrini.net/a-homegrown-python-bread-crumb-module/)(如[問題]中提到的) (http://stackoverflow.com/q/13444666/445073))呢?你嘗試過嗎? – Day

+0

是的,我看着它,但我不是它的粉絲,只是拉下網址,因爲我想定製的話是什麼。我正在尋找最簡單的方法來做一個像@ breadtrail(['Crumb A',url_for('...)],['Crumb B',url_for('...)])的裝飾器,並且總是通過breadtrail var將這些數據填充到jinja,而無需爲每條路線輸入breadtrail = breadtrail。 – chrickso