2014-05-07 105 views
2

是否有可能在燒瓶中定義處理url某個部分的url路由器並將url傳遞給下一個url處理程序的進一步處理?燒瓶多個URL處理程序部分處理URL

用例將是一個url中的靜態部分,它會重複很多並始終需要相同的處理。 /user/1/something

/user/1/something-else

/user/2/...

理想情況下,處理程序將處理/user/<id>部分(負荷數據庫記錄等),並將結果存入當地情況。另一個處理程序會處理剩餘的url。這將使我也/user/<name/更換user部分(例如不接觸的其它路由器。

這是可能的燒瓶,如果是這樣,我怎麼了?

+1

你確定你只是不需要轉換器?這看起來像是轉換器的情況。 – jaime

+0

你是什麼意思?你能詳細說明嗎? – orange

回答

3

我不知道你能做些什麼你想然而,從以上您介紹的使用方法,我想你只需要一個轉換器

請告訴我A轉換器

就是這麼神奇,可以讓你定義像這樣的路線:?

@app.route('/double/<int:number>') 
def double(number): 
    return '%d' % (number * 2) 

以上,路線只接受/ double/ints。更好的是,無論在URL的部分傳遞的是轉換爲int。因此,轉換器的名字:D。

轉換器的格式爲<converter:variable_name>。你可以閱讀關於Flask的內置轉換器here

關於轉換器最好的部分是,你可以編寫自己的自定義數據類型!要做到這一點,只需從werkzeug.routing.BaseConverter派生並填入to_python和to_url即可。下面,我爲無處不在的用戶對象創建了一個簡單的轉換器。

class UserConverter(BaseConverter): 
    """Converts Users for flask URLs.""" 

    def to_python(self, value): 
     """Called to convert a `value` to its python equivalent. 

     Here, we convert `value` to a User. 
     """ 
     # Anytime an invalid value is provided, raise ValidationError. Flask 
     # will catch this, and continue searching the other routes. First, 
     # check that value is an integer, if not there is no way it could be 
     # a user. 
     if not value.isdigit(): 
      raise ValidationError() 
     user_id = int(value) 

     # Look up the user in the database. 
     if user_id not in _database: 
      raise ValidationError() 

     # Otherwise, return the user. 
     return _database[user_id] 

    def to_url(self, value): 
     """Called to convert a `value` to its `url` equivalent. 

     Here we convert `value`, the User object to an integer - the user id. 
     """ 
     return str(value.id) 

轉換器什麼時候被調用?

當燒瓶匹配您的路線,並需要填寫由您的轉換器處理的點。因此,根據以下路線 - /find/<user:user>,以下所有網址均由我們的轉換器處理。

  1. /查找/ 1
  2. /查找/ 2
  3. /查找/雅伊梅蘇拉
  4. /查找/ zasdf123

對於URL的上述情況,UserConverter.to_python方法被調用以'1','2','jaime'和'zasdf123'。確定這些值是否轉化爲有效用戶的方法取決於該方法。如果是,則將有效用戶直接傳遞給路由的user參數。

但是,燒瓶仍然需要知道關於您的新轉換器。說起來很簡單:

app.url_map.converters['user'] = UserConverter 

最後的自定義轉換器的很酷的功能是他們讓建築URL是一個自然的,簡單的過程。要創建一個網址,只需要:

url_for('find_user', user=user) 

最後,一個簡單的程序將所有這一切聯繫在一起。

from flask import Flask, url_for 
from werkzeug.routing import BaseConverter, ValidationError 


class User: 

    def __init__(self, id, name): 
     self.id = id 
     self.name = name 


class UserConverter(BaseConverter): 
    """Converts Users for flask URLs.""" 

    def to_python(self, value): 
     """Called to convert a `value` to its python equivalent. 

     Here, we convert `value` to a User. 
     """ 
     # Anytime an invalid value is provided, raise ValidationError. Flask 
     # will catch this, and continue searching the other routes. First, 
     # check that value is an integer, if not there is no way it could be 
     # a user. 
     if not value.isdigit(): 
      raise ValidationError() 
     user_id = int(value) 

     # Look up the user in the database. 
     if user_id not in _database: 
      raise ValidationError() 

     # Otherwise, return the user. 
     return _database[user_id] 

    def to_url(self, value): 
     """Called to convert a `value` to its `url` equivalent. 

     Here we convert `value`, the User object to an integer - the user id. 
     """ 
     return str(value.id) 


# Create a `database` of users. 
_database = { 
    1: User(1, 'Bob'), 
    2: User(2, 'Jim'), 
    3: User(3, 'Ben') 
} 

app = Flask(__name__) 
app.url_map.converters['user'] = UserConverter 

@app.route('/find/<user:user>') 
def find_user(user): 
    return "User: %s" % user.name 

@app.route('/find/<user:user>/extrapath') 
def find_userextra(user): 
    return 'User extra: %s' % user.name 

@app.route('/users') 
def list_users(): 
    # Return some broken HTML showing url's to our users. 
    s = '' 
    for user in _database.values(): 
     s += url_for('find_user', user=user) + '<br/>' 
    return s 

if __name__ == '__main__': 
    app.run(debug=True) 

如果事情是不明確,或喘息一個存在bug,讓我知道:d。這適用於你的問題,因爲你提到的一系列的網址即開始一樣 -

/user/1/something

/user/1/something-else

/user/2/

對於這些路由你會應用自定義轉換器,像這樣:

@app.route('/user/<user:user>/something') 

@app.route('/user/<user:user>/something-else') 

@app.route('/user/<user:user>/) 
+0

有趣。我不知道這件事。在你的例子中,你是否可以添加一些演示'@ app.route('/ find//more')'的路線?我懷疑它是如此簡單,但只是想仔細檢查一下。 – orange

+0

順便說一句,很好的描述! – orange

+1

我增加了一條額外的路線。它確實如此簡單。 @ app.route('/ find//extrapath')或許最好的方式來考慮它 - 在你需要'用戶'的任何地方,將它放在url中,然後你自動在路由的函數中接收它。 – jaime