URL Mapping (or URL Routing) is not a big topic in Flask. The Flask documentation has a very short
section on URL Route Registrations.
Miguel Grinberg’s Flask Web Development (2nd) book only discusses the topic briefly on pages 8-9 and 36-38.
The route
decorator is very straightforward to use in Flask.
@app.route('/)
def index():
....
@app.route('/user/<name>')
def user(name):
....
You can define the route function first and call add_url_rule
method of Flask class to
add the url rule.
def index():
....
app.add_url_rule('/', 'index', index)
If the URL mapping is only one directional that maps a URL route to a function, the Python code
implementing it should be simple. The URL mapping can also do reverse mapping.
When you have an end point name index
, you can call url_for('index')
to get the URL route /
, or
call url_for('user', name='john')
to get the route /user/john
.
Let’s look at the Flask source code to know more about URL mapping. The __init__
method
of Flask class defines an instance variable url_map
on Line 582.
self.url_map = self.url_map_class()
self.url_map.host_matching = host_matching
The url_map_class
is a class variable defined on Line 366 which is Map
class imported
from werkzeug.routing
module.
The add_url_rule
method is defined on Line 1177 in app.py module. The method is quite
long, and part of the code is shown below.
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
...
rule = self.url_rule_class(rule, methods=methods, **options)
...
self.url_map.add(rule)
...
if view_func is not None:
...
self.view_functions[endpoint] = view_func
The url_rule_class
is referring to Rule
class imported from werkzeug.routing
.
The view_functions
is one of the instance variables (dictionary) of Flask class
defined on Line 444.
The route
decorator is defined on Line 1288. It calls the add_url_method
method,
and the code is shown below.
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
The route
decorator is interesting. If you read Miguel Grinberg’s
ultimate guide to Python decorators,
it is a combination of Function Registration and Decorators with
Arguments.
The URL reverse function url_for
is defined on Line 226 of helpers.py
module. The functions retrieves a url_adapter
from request context or
app context, and calls build
method on url_adapter
to return the
reversed URL.
appctx = _app_ctx_stack.top
reqctx = _request_ctx_stack.top
if reqctx is not None:
url_adapter = reqctx.url_adapter
...
else:
url_adapter = appctx.url_adapter
...
rv = url_adapter.build(
endpoint, values, method=method, force_external=external
)
When does this url_adapter
is initialized? The url_adapter
is one of
instance variables of RequestContext
class defined on Line 290 in ctx.py module.
def __init__(self, app, environ, request=None, session=None):
....
self.url_adapter = None
try:
self.url_adapter = app.create_url_adapter(self.request)
...
The url_adapter
is also one of the instance variables of AppContext
class
defined on Line 216 in ctx.py module.
def __init__(self, app):
...
self.url_adapter = app.create_url_adapter(None)
The create_url_adapter
method of Flask
class calls bind_to_environ
or
bind
method of Map
class to create an instance of MapAdapter
class, which
is also defined in werkzeug
routing
module.
The actual URL mapping happens on Line 2447 of app.py module (inside wsgi_app
method) in Flask. It calls full_dispatch_request
method of Flask class, which is
defined on Line 1938. It then calls dispatch_request
method, which is
in turn defined on Line 1914.
def dispatch_request(self):
"""Does the request dispatching. Matches the URL and returns the
return value of the view or error handler. ...
"""
...
return self.view_functions[rule.endpoint](**req.view_args)
The method simply uses the view_functions
instance variable (a dictionary)
to find the corresponding view function for the URL.
The URL Routing functions are mainly provided by the Werkzeug package, which is one of the dependent packages of Flask. The Werkzeug documentation has a page specifically for URL Routing.