Nhận danh sách tất cả các tuyến đường được xác định trong ứng dụng Flask


145

Tôi có một ứng dụng web dựa trên Flask phức tạp. Có rất nhiều tập tin riêng biệt với chức năng xem. URL của họ được xác định với @app.route('/...')trang trí. Có cách nào để có được danh sách tất cả các tuyến đường đã được khai báo trong ứng dụng của tôi không? Có lẽ có một số phương pháp tôi có thể gọi trên appđối tượng?

Câu trả lời:


152

Tất cả các tuyến đường cho một ứng dụng được lưu trữ trên app.url_mapđó là một thể hiện của werkzeug.routing.Map. Bạn có thể lặp lại qua các Rulethể hiện bằng cách sử dụng iter_rulesphương thức:

from flask import Flask, url_for

app = Flask(__name__)

def has_no_empty_params(rule):
    defaults = rule.defaults if rule.defaults is not None else ()
    arguments = rule.arguments if rule.arguments is not None else ()
    return len(defaults) >= len(arguments)


@app.route("/site-map")
def site_map():
    links = []
    for rule in app.url_map.iter_rules():
        # Filter out rules we can't navigate to in a browser
        # and rules that require parameters
        if "GET" in rule.methods and has_no_empty_params(rule):
            url = url_for(rule.endpoint, **(rule.defaults or {}))
            links.append((url, rule.endpoint))
    # links is now a list of url, endpoint tuples

Xem Hiển thị liên kết đến các trang web mới được tạo để biết thêm một chút thông tin.


Ngọt! Ngoại trừ tôi có một vấn đề với dòng url = url_for(rule.endpoint). Tôi vừa nhận được lỗi này BuildError: ('DeleteEvent', {}, None). Thay vào đó, để có được url tôi vừa làm url = rule.rule. Bất cứ ý tưởng tại sao phương pháp của bạn không làm việc cho tôi?
J-bob

@ J-bob - rất có thể tuyến đường được liên kết DeleteEventcó tham số bắt buộc - bạn có thể chọn trường hợp đặc biệt hoặc lọc bất kỳ quy tắc nào trong đólen(rule.arguments) > len(rule.defaults)
Sean Vieira

Oh tôi nghĩ rằng tôi nhận được nó. url_forkhông thể tạo URL cho methid đó mà không có tham số, phải không? OK, nhưng có vẻ như phương thức của tôi vẫn hoạt động, nó chỉ giữ phần đó nếu URL là một tham số. Cảm ơn!
J-bob

1
Đây là một khởi đầu tuyệt vời. Bất kỳ đề xuất nào về cách tạo một dịch vụ web dựa trên bình tự ghi đầy đủ, trong đó tất cả các tham số (chẳng hạn như? Spam = "trứng") được liệt kê? Có lẽ thông tin này có thể được trích xuất từ ​​một chuỗi của một phương thức thực hiện.
Leonid

2
Thay vì sử url_for(rule.endpoint)dụng rule.rule, đó là cách giải quyết tốt hơn nhiều trường hợp bạn có nhiều hơn một tuyến đường cho cùng một phương thức.
Zini

82

Tôi chỉ gặp câu hỏi tương tự. Những giải pháp trên quá phức tạp. Chỉ cần mở một shell mới trong dự án của bạn:

    python
    >>> from app import app
    >>> app.url_map

' Ứng dụng ' đầu tiên là tập lệnh dự án của tôi: app.py , một ứng dụng khác là tên web của tôi.

(giải pháp này dành cho web nhỏ với một tuyến đường nhỏ)


1
Điều này có lẽ không trả lời trực tiếp câu hỏi. Nhưng nó chắc chắn xứng đáng nhiều upvote hơn.
UltraInstotype

Câu trả lời này rất tốt cho việc không yêu cầu bạn thêm bất kỳ mã nào vào ứng dụng của bạn. Tôi đã sử dụng nó để có được câu trả lời tôi muốn trong vài giây mà không cần xây dựng lại mã của mình.
joshdick

"Có cách nào để có được danh sách tất cả các tuyến đường đã được khai báo trong suốt ứng dụng của tôi không?" Tôi nghĩ rằng điều này trả lời câu hỏi trực tiếp và nên là câu trả lời được chấp nhận. Quá dễ. Cảm ơn.
andho

2
Tôi thực sự không thấy cách này đơn giản hay rõ ràng hơn câu trả lời được chấp nhận. Đó là đề xuất cách tiếp cận tương tự, nhưng mất nhiều thời gian hơn để đi đến điểm và không chỉ ra cách lặp lại qua Mapthể hiện hoặc truy cập bất kỳ thuộc tính nào của Rulenó, mà không thực sự bạn có thể làm gì hữu ích.
Đánh dấu Amery

57

Tôi thực hiện một phương thức trợ giúp trên manage.py:

@manager.command
def list_routes():
    import urllib
    output = []
    for rule in app.url_map.iter_rules():

        options = {}
        for arg in rule.arguments:
            options[arg] = "[{0}]".format(arg)

        methods = ','.join(rule.methods)
        url = url_for(rule.endpoint, **options)
        line = urllib.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, url))
        output.append(line)

    for line in sorted(output):
        print line

Nó giải quyết các đối số còn thiếu bằng cách xây dựng một tập hợp các tùy chọn giả. Đầu ra trông như sau:

CampaignView:edit              HEAD,OPTIONS,GET     /account/[account_id]/campaigns/[campaign_id]/edit
CampaignView:get               HEAD,OPTIONS,GET     /account/[account_id]/campaign/[campaign_id]
CampaignView:new               HEAD,OPTIONS,GET     /account/[account_id]/new

Sau đó để chạy nó:

python manage.py list_routes

Để biết thêm về kiểm tra quản lý: http://flask-script.readthedocs.org/en/latest/


5
Các công việc trên rất tốt. Chỉ cần thay đổi urllib.unquoteđể urllib.parse.unquoteprint lineđể print(line)và nó hoạt động trong python 3.x là tốt.
vắt

1
Điều này không hoạt động đối với các đối số không phải chuỗi, thay vào đó tôi khuyên bạn nên sử dụng câu trả lời của John Jiang.
nico

42

Tương tự như câu trả lời của Jonathan, tôi đã chọn làm điều này thay vào đó. Tôi không thấy điểm sử dụng url_for vì nó sẽ bị hỏng nếu đối số của bạn không phải là chuỗi, ví dụ: float

@manager.command
def list_routes():
    import urllib

    output = []
    for rule in app.url_map.iter_rules():
        methods = ','.join(rule.methods)
        line = urllib.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, rule))
        output.append(line)

    for line in sorted(output):
        print(line)

31

Rõ ràng, kể từ phiên bản 0.11, Flask có CLI tích hợp . Một trong các lệnh tích hợp liệt kê các tuyến:

FLASK_APP='my_project.app' flask routes

Điều này là hoàn toàn xuất sắc!
pfabri

1
flask urlsđối với tôi (0.12.1). Tôi thấy điều đó flask --helpnhưng tôi không thấy các tuyến đường hoặc url trên trang CLI
mrgnw

các tuyến đường dường như được gỡ bỏ trong bình 1.1.2
Jerry Ji

5

Vì bạn không chỉ định rằng nó phải được chạy dòng lệnh, nên những điều sau đây có thể dễ dàng được trả về trong json cho bảng điều khiển hoặc giao diện không phải dòng lệnh khác. Dù sao, kết quả và đầu ra thực sự không nên được xử lý theo quan điểm thiết kế. Đó là thiết kế chương trình tồi, ngay cả khi đó là một chương trình nhỏ. Kết quả dưới đây sau đó có thể được sử dụng trong một ứng dụng web, dòng lệnh hoặc bất cứ thứ gì khác ăn vào json.

Bạn cũng không xác định rằng bạn cần biết chức năng python liên quan đến từng tuyến đường, vì vậy điều này trả lời chính xác hơn câu hỏi ban đầu của bạn.

Tôi sử dụng bên dưới để thêm đầu ra vào bảng điều khiển giám sát. Nếu bạn muốn các phương thức định tuyến khả dụng (GET, POST, PUT, v.v.), bạn sẽ cần kết hợp nó với các câu trả lời khác ở trên.

Quy tắc repr () đảm nhiệm việc chuyển đổi các đối số cần thiết trong tuyến đường.

def list_routes():
    routes = []

    for rule in app.url_map.iter_rules():
        routes.append('%s' % rule)

    return routes

Điều tương tự bằng cách sử dụng một danh sách hiểu:

def list_routes():
    return ['%s' % rule for rule in app.url_map.iter_rules()]

Đầu ra mẫu:

{
  "routes": [
    "/endpoint1", 
    "/nested/service/endpoint2", 
    "/favicon.ico", 
    "/static/<path:filename>"
  ]
}

2

Nếu bạn cần truy cập vào các chức năng xem, sau đó thay vì app.url_mapsử dụngapp.view_functions .

Kịch bản ví dụ:

from flask import Flask

app = Flask(__name__)

@app.route('/foo/bar')
def route1():
    pass

@app.route('/qux/baz')
def route2():
    pass

for name, func in app.view_functions.items():
    print(name)
    print(func)
    print()

Đầu ra từ việc chạy đoạn script trên:

static
<bound method _PackageBoundObject.send_static_file of <Flask '__main__'>>

route1
<function route1 at 0x128f1b9d8>

route2
<function route2 at 0x128f1ba60>

(Lưu ý việc bao gồm tuyến "tĩnh", được tạo tự động bởi Flask.)


2

Bạn có thể xem tất cả các Tuyến thông qua vỏ bình bằng cách chạy các lệnh sau sau khi xuất hoặc đặt biến môi trường FLASK_APP. flask shell app.url_map


1

trong ứng dụng bình của bạn làm:

flask shell
>>> app.url_map
Map([<Rule '/' (OPTIONS, HEAD, GET) -> helloworld>,
 <Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.