2011-10-16 17 views

Trả lời

58

Ok. Phải mất một số delving vào mã werkzeug.routingflask.helpers.url_for, nhưng tôi đã tìm ra. Bạn chỉ cần thay đổi endpoint cho các tuyến đường (hay nói cách khác, bạn tên tuyến đường của bạn)

@app.route("/canonical/path/", endpoint="foo-canonical") 
@app.route("/alternate/path/") 
def foo(): 
    return "hi!" 

@app.route("/wheee") 
def bar(): 
    return "canonical path is %s, alternative is %s" % (url_for("foo-canonical"), url_for("foo")) 

sẽ sản xuất

con đường kinh điển là/kinh điển/path /, thay thế là/thay thế/path/

Có một nhược điểm của phương pháp này. Flask luôn ràng buộc tuyến đường được xác định cuối cùng đến điểm cuối được xác định hoàn toàn (foo trong mã của bạn). Đoán xem điều gì sẽ xảy ra nếu bạn xác định lại điểm cuối? Tất cả url_for('old_endpoint') của bạn sẽ ném werkzeug.routing.BuildError. Vì vậy, tôi đoán là giải pháp phù hợp với toàn bộ vấn đề được xác định con đường kinh điển cuối cùng và tên thay thế:

""" 
    since url_for('foo') will be used for canonical path 
    we don't have other options rather then defining an endpoint for 
    alternative path, so we can use it with url_for 
""" 
@app.route('/alternative/path', endpoint='foo-alternative') 
""" 
    we dont wanna mess with the endpoint here - 
    we want url_for('foo') to be pointing to the canonical path 
""" 
@app.route('/canonical/path') 
def foo(): 
    pass 

@app.route('/wheee') 
def bar(): 
    return "canonical path is %s, alternative is %s" % (url_for("foo"), url_for("foo-alternative")) 
+1

Thật là một câu trả lời toàn diện và đáng yêu. Hãy cho tôi một cơ hội để xác minh và tôi sẽ đánh dấu nó được chấp nhận. Bạn có thể nên gửi nó cho những người pocoo để nó được chính thức ghi nhận. – jiggy

+0

Ok, đã có một số rắc rối với điều này cho đến khi tôi nâng cấp lên bình 0.8 (không thành công với 0.7.2). Nó cũng dường như được chọn lên chú thích đầu tiên, không phải là chú thích cuối cùng cho tôi. Dù bằng cách nào, param điểm cuối là khóa. – jiggy

48

quy tắc trong Flask là duy nhất. Nếu bạn xác định cùng một URL tuyệt đối cho cùng một chức năng, nó sẽ mặc định xung đột vì bạn đang làm điều gì đó mà chúng tôi ngăn bạn làm từ quan điểm của chúng tôi là sai.

Có một lý do khiến bạn muốn có nhiều URL đến cùng điểm cuối tuyệt đối và tương thích ngược với quy tắc đã tồn tại trong quá khứ. Kể từ WZ0.8 và Flask 0.8 bạn có thể xác định rõ ràng một bí danh cho một tuyến đường:

@app.route('/') 
@app.route('/index.html', alias=True) 
def index(): 
    return ... 

Trong trường hợp này nếu người dùng yêu cầu /index.html Flask sẽ tự động đưa ra một vĩnh viễn chuyển hướng đến chỉ /.

Điều đó không có nghĩa là một chức năng không thể bị ràng buộc để nhiều hơn một url Mặc dù vậy, nhưng trong trường hợp này, bạn sẽ cần phải thay đổi thiết bị đầu cuối:

@app.route('/') 
def index(): 
    ... 

app.add_url_rule('/index.html', view_func=index, endpoint='alt_index') 

Hoặc cách khác:

@app.route('/') 
@app.route('/index.html', endpoint='alt_index') 
def index(): 
    ... 

Trong trường hợp này, bạn có thể xác định một lần xem lần thứ hai dưới một tên khác. Tuy nhiên đây là điều bạn thường muốn tránh vì sau đó chức năng xem sẽ phải kiểm tra request.endpoint để xem những gì được gọi. Thay vì làm tốt hơn một cái gì đó như thế này:

@app.route('/') 
def index(): 
    return _index(alt=False) 

@app.route('/index.html') 
def alt_index(): 
    return _index(alt=True) 

def _index(alt): 
    ... 

Trong cả hai trường hợp thế hệ URL là url_for('index') hoặc url_for('alt_index').

Bạn cũng có thể làm điều này trên mức độ hệ thống định tuyến:

@app.route('/', defaults={'alt': False}) 
@app.route('/index.html', defaults={'alt': True}) 
def index(alt): 
    ... 

Trong trường hợp này hệ url là url_for('index', alt=True) hoặc url_for('index', alt=False).

+0

Nó sẽ là tốt đẹp để có điều này trong tài liệu (hoặc là nó đã có? Không thể tìm thấy). Ví dụ cuối cùng của bạn chính xác là những gì cần thiết cho tôi. – aplavin

0

Ngoài ra, đối với những người sử dụng bắt tất cả tuyến đường được tạo bằng các biến: Flask sẽ tạo đường dẫn url chính xác nếu url_for được chuyển một từ điển chứa các biến.

Ví dụ ...

app.py:

app.route('/<path:pattern1>') 
app.route('/<path:pattern1>/<path:pattern2>') 
def catch_all(pattern1, pattern2=None): 
    return render_template('template.html', p1=pattern1, p2=pattern2) 

app.route('/test') 
def test_routing: 
    args = {'pattern1': 'Posts', 'pattern2': 'create'} 
    return render_template('test.html', args=args) 

test.html:

<a href="{{url_for('catch_all', **args)}}">click here</a> 

Khi bạn nhấp vào liên kết 'nhấp vào đây', bạn sẽ được hướng dẫn đến tuyến 'Bài đăng/tạo'.

Các vấn đề liên quan