[Flask] Confused by an unexpected route-to-function mapping

Skip Montanaro skip.montanaro at gmail.com
Mon Dec 27 06:32:45 EST 2021


I'm returning to Flask after several years away (and never having done much
of any significance with it before). I'm having trouble with the mapping
between routes and the functions which handle them.

I have two functions, each of which is meant to handle a number of related
routes. The first is just supposed to normalize things and do a permanent
redirect to the second

@app.route('/<int:year>-<int:month>/html/<filename>')
@app.route('/CR/<int:year>-<int:month>/html/<filename>')
@app.route('/<int:year>-<int:month>')
@app.route('/<int:year>-<int:month>/<filename>')
def old_cr_month(year, month, filename="index.html"):
    print(">> old_cr_month:", year, month, filename)

    raise Exception

    return redirect(url_for("cr", year=year, month=month,
                            filename=filename),
                    code=301)


@app.route("/CR")
@app.route("/CR/")
@app.route('/CR/<int:year>/<int:month>')
@app.route('/CR/<int:year>/<int:month>/<filename>')
def cr(year=None, month=None, filename="index.html"):
    print(">> cr:", year, month, filename)
    ...


When I visit this URL:

http://super.secret.website/CR/2000-09/html/maillist.html


old_cr_month is called, as I expect. Its print function is called and the
embedded exception is raised.

When I visit this URL:

http://super.secret.website/CR/2000-09/html/threads.html


the old_cr_month handler isn't called. Instead, the cr function is enlisted
to handle the request and its print function is called. Strangely, it does
seem to get year, month and filename correct. This despite none of the
defined routes for cr having URL templates with either the year-month form
or an embedded html directory in the middle.

When I dump the app object in the debugger the displayed url_map looks to
me like old_cr_month should have handled the URL (my candidate route
mapping highlighted in red).

Map([<Rule '/hello' (HEAD, OPTIONS, GET) -> hello>,
 <Rule '/CR/' (HEAD, OPTIONS, GET) -> cr>,
 <Rule '/CR' (HEAD, OPTIONS, GET) -> cr>,
 <Rule '/' (HEAD, OPTIONS, GET) -> index>,
 <Rule '/CR/<year>-<month>/html/<filename>' (HEAD, OPTIONS, GET) ->
old_cr_month>,
 <Rule '/<year>-<month>/html/<filename>' (HEAD, OPTIONS, GET) ->
old_cr_month>,
 <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/CR/<year>/<month>/<msg>' (HEAD, OPTIONS, GET) -> cr_message>,
 <Rule '/CR/<year>/<month>/<filename>' (HEAD, OPTIONS, GET) -> cr>,
 <Rule '/CR/<year>/<month>' (HEAD, OPTIONS, GET) -> cr>,
 <Rule '/<year>-<month>/<filename>' (HEAD, OPTIONS, GET) -> old_cr_month>,
 <Rule '/<year>-<month>' (HEAD, OPTIONS, GET) -> old_cr_month>])


Here's my setup:

$ flask --version
Python 3.10.1
Flask 2.0.2
Werkzeug 2.0.2


I'm running in an Ubuntu 20.04 VM.

What am I missing about routes here? How can two so similarly structured
URLs be mapped to different handler functions? Is there something I can do
to dig into the URL-to-handler mapping process?

Thx,

Skip Montanaro
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/pipermail/flask/attachments/20211227/479f85db/attachment.html>


More information about the Flask mailing list