- The concept of routing (Route) is very important in all web frameworks. It is used to define the mapping relationship between URLs and corresponding processing functions (views). By defining routes, web framework applications can respond to different URL requests and execute corresponding logic.
Source code analysis:
When the Flask project (such as the hello world project below) is just started, Flask will definitely create a corresponding relationship between all routes and views.
from flask import Flask
app = Flask(__name__)
@app.route('/index', methods=['GET', 'POST'])
def index():
return 'hello world'
if __name__ == '__main__':
app.run('localhost', 4000)
Analysis source code:
When the program runs @app.route('/index', methods=['GET', 'POST'])
, due to the existence of @ syntax sugar, the route function will be executed immediately, so enter the route function source code tracking:
The execution of the route function of the app object will return the decorator function, that is, @decorator is equivalent to @app.route('/index', methods=['GET', 'POST'])
The existence of @grammatical sugar will immediately execute @decorator
Namely decorator (index function)
[Because the index() function is not executed below the program, there is no need to continue to read the second step of @grammatical sugar ( details are explained in the article "(3) Flask Pre-Knowledge Stack - Decorator" )]
Continue to look at the source code of the route function, the decorator (index function) corresponds to —> the parameter f in the decorator is the index function.
self.add_url_rule(rule, endpoint, f, **options)
This sentence in the source code is the key, and its function is to add corresponding rules for routing and view functions.
Continue to track the source code and look at this function:
[Note that the function is in this object]add
_url_rul
e()
Flask(__name__)
The key point is the red box in the above picture.
A simple analysis of the source code of the above picture add_url_rule()
:
add_url_rule()
Methods are ways to register URL rules in your Flask application.
def add_url_rule(
self,
rule: str,
endpoint: t.Optional[str] = None,
view_func: t.Optional[ft.RouteCallable] = None,
provide_automatic_options: t.Optional[bool] = None,
**options: t.Any,
) -> None:
"""
* rule:URL规则的字符串表示,对应'/index'。
* endpoint:可选参数,指定URL规则的名称(即终点)。
* view_func:可选参数,指定与URL规则关联的处理函数(视图函数)。
* provide_automatic_options:可选参数,控制是否自动提供OPTIONS方法。
"""
First, the method processes and validates the parameters:
# 如果没有指定`endpoint`,则根据`view_func`自动生成一个。
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options["endpoint"] = endpoint
# 从options参数中弹出`methods`字段,并根据不同情况设置默认值为"GET"。最后,将`methods`转换为大写,并确保它是一个集合。
methods = options.pop("methods", None)
if methods is None:
methods = getattr(view_func, "methods", None) or ("GET",)
if isinstance(methods, str):
raise TypeError("Allowed methods must be a list of strings, for example: @app.route(..., methods=['POST'])")
methods = {
item.upper() for item in methods}
Next, according to view_func
the attributes and parameter values, set whether to automatically provide the OPTIONS method (we will briefly explain what this is at the end of the article):
# 如果没有指定`provide_automatic_options`,则从`view_func`的属性中获取。
if provide_automatic_options is None:
provide_automatic_options = getattr(view_func, "provide_automatic_options", None)
# 如果仍然未指定,则根据methods是否包含"OPTIONS"来决定是否自动提供OPTIONS方法。
if provide_automatic_options is None:
if "OPTIONS" not in methods:
provide_automatic_options = True
required_methods.add("OPTIONS")
else:
provide_automatic_options = False
Next, add the required methods to methods
the collection and create an Rule
object to represent URL rules:
# 将必需的方法合并到`methods`集合中(文末会讲这样的作用)
methods |= required_methods
# 使用`url_rule_class`创建一个`Rule`对象来表示URL规则
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
# 将rule添加到应用程序的URL映射中。
self.url_map.add(rule)
Finally, if specified view_func
, associate it with endpoint
, and check for conflicts:
if view_func is not None:
old_func = self.view_functions.get(endpoint)
if old_func is not None and old_func != view_func:
raise AssertionError(f"View function mapping is overwriting an existing endpoint function: {
endpoint}")
self.view_functions[endpoint] = view_func
If there is already a endpoint
processing function associated with it before, it will be raised AssertionError
(familiar? The problem Flask raised in the decorator is the exception thrown here!!!).
Summary: add_url_rule()
Method for adding URL rules to a Flask application. It parses and validates parameters, sets default values, and creates and registers Rule
objects to represent URL rules. Then, associate a handler function with the URL rule and perform the necessary conflict checks.
Continue to press ① to track the source code:
My humble translation:
A Rule represents a URL pattern. A "Rule" has options that change how it behaves, and are passed to the "Rule" constructor.
Note that all arguments must be keyword arguments, except for rule strings, so as not to break the application when Werkzeug is upgraded.
To put it bluntly:
Rule
Class to parse and store URL patterns. Rule
A class represents a URL rule and contains information associated with it, such as URL pattern, HTTP method, handler function, etc.
Continue to press ② to track the source code:
Enter url_map:
Enter url_map_class
:
My humble translation:
The map class stores all URL rules and some configuration parameters. Some config values are only stored in 'Map' instances as they affect all rules, others are just default values
and can be overridden for each rule. Note that all parameters except ' rules ' as keyword arguments must be specified!
In short, in one sentence:
Map
is a URL mapper, which is used to store and manage all URL rules in the application.
Continue to track the add() function in the Map class (the comments are very clear~):
Continue to press ③ to track the source code (we will briefly talk about this line of source code at the end of the article):
The above is the source code of the three lines analyzed separately. It is just a simple analysis, and the follow-up will gradually deepen.
view_functions
, Map
and Rule
put it together to see:
view_functions
There is a close relationship between Map
, and . Rule
They are important components in the Flask framework for handling URL routing.
-
view_functions
It is an attribute of the Flask application object, which stores the mapping relationship between all routing endpoints (endpoint) and corresponding view functions (view function) in the application. It is a dictionary where the key is the endpoint name of the route and the value is the corresponding view function.app.view_functions
This dictionary can be accessed and manipulated via . -
Map
is a URL mapper that stores and manages all URL rules in your application. It iswerkzeug.routing.Map
an instance of the class through whichapp.url_map
the application'sMap
objects can be accessed.Map
The class provides methods for adding, finding and manipulating URL rules, includingadd()
,match()
,iter_rules()
and so on. -
Rule
It is the representation of URL rules, which defines a URL pattern, bound view functions, acceptable request methods and other information.Rule
A class iswerkzeug.routing.Rule
an instance of a class,Map
used as part of an object. EachRule
object has a unique endpoint that identifies the rule.Map
Classes useRule
objects to store and manage URL rules.
The relationship is as follows:
- When defining a Flask application, we use
@app.route()
decorators to create URL rules and associate route endpoints with view functions. These URL rules will be stored inMap
the object, byapp.url_map
accessing. app.route()
When the decorator is called , anRule
object is created inside the Flask framework to represent the URL rule. Objects are thenRule
added toMap
objects to form the entire URL mapping.Map
Objects useview_functions
properties to find and call corresponding view functions. When a request arrives,Map
it will internally search for a matchingRule
object based on the requested URL path and HTTP method, and obtain the bound view function from it.- Through the combination of
view_functions
dictionaries andMap
objects, Flask can realize the functions of automatic routing and request processing. It uses the endpoint of the URL as aview_functions
key to find the corresponding view function; at the same time, according to the requested URL and method,Map
finds the matchingRule
object and extracts the view function to call it.
It can be seen that , view_functions
, Map
and Rule
are the key components for processing URL routing in the Flask framework. They cooperate with each other to achieve flexible routing management and request processing mechanisms.
To sum up—two ways to add routes:
from flask import Flask
app = Flask(__name__)
app.config.from_object()
# 方式一 (就用这个!)
@app.route('/index', methods=['GET', 'POST'])
def index():
return 'index'
def order():
return 'order'
# 方式二
app.add_url_rule('/order', view_func=order)
if __name__ == '__main__':
app.run('localhost', 4000)
expand:
(1) In-depth provide_automatic_options
parameters
provide_automatic_options
parameter is used to control whether the OPTIONS method is automatically provided.
In the HTTP protocol, the OPTIONS method is used to obtain the request methods supported by the specified URL. The Flask framework automatically handles OPTIONS requests by default and returns a response containing the allowed request methods.
When provide_automatic_options
the parameter is True, it means that the application will automatically provide support for the OPTIONS method. If the requested URL matches a routing rule, but does not explicitly define a handler for the OPTIONS method, Flask will automatically generate a handler for the OPTIONS method to respond to the request.
When provide_automatic_options
the parameter is False, it means that the application will not automatically provide support for the OPTIONS method. Even if the requested URL matches a routing rule, but does not explicitly define a handler for the OPTIONS method, Flask will not automatically generate a handler for the OPTIONS method. This means that if the client sends an OPTIONS request, and there is no corresponding handler function to handle the request, Flask will return a 405 Method Not Allowed response.
By setting provide_automatic_options
parameters, developers can flexibly control whether the application automatically provides support for the OPTIONS method to meet specific needs.
(2) methods |= required_methods
Function
methods |= required_methods
is the operation used during route definition in Flask to merge required methods into the set of acceptable methods.
In Flask, the allowed request methods can be specified by passing the request method as a decorator parameter to the routing function. For example:
@app.route('/', methods=['GET', 'POST'])
def index():
# 处理GET和POST请求
pass
In the above example, the routing function index()
is defined to only accept GET and POST requests. But sometimes, you may also need to deal with other methods, such as OPTIONS or PUT, etc. That's required_methods
what it does.
required_methods
is a collection containing methods that should always be added to the set of acceptable methods. These methods are usually application-specific and must be supported.
|=
Merge required_methods
the sets into sets by using the bitwise OR (OR) operator methods
, and assign the result to methods
. This ensures that methods
all required methods are included in the collection.
For example, if methods
the collection already contained ['GET'] and required_methods
the collection contained ['OPTIONS'], then methods |= required_methods
after execution, methods
the collection would become ['GET', 'OPTIONS'].
The purpose of this is to ensure that the route can handle all required request methods, thus providing more comprehensive HTTP method support.
(3) In-depthself.view_functions
self.view_functions
Is a dictionary used to store the mapping relationship between all routing endpoints (endpoints) and corresponding view functions (view functions) in the Flask application.
It is created during initialization of the Flask application object and exists as an instance property. self.view_functions
The definition of the dictionary is as follows:
self.view_functions: Dict[str, Callable] = {
}
This is meant self.view_functions
to be a dictionary of key-value pairs, where the key is the endpoint name of the route and the value is the corresponding view function. Specifically, keys are strings and values are callables, usually Python functions.
When @app.route()
defining routes with decorators, the Flask framework automatically adds route endpoints and corresponding view functions to self.view_functions
the dictionary. In this way, when receiving a request, Flask can find the corresponding view function from the dictionary according to the routing end point, and execute the corresponding logic.
Practical combat - how to use self.view_functions
dictionaries:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def demo():
return 'Hello, World!'
@app.route('/index')
def index():
return 'index'
if __name__ == '__main__':
print(app.view_functions)
Running it will output app.view_functions
the contents of the dictionary:
{
'static': <function Flask.__init__.<locals>.<lambda> at 0x000001A3334258B0>,
'demo': <function demo at 0x000001A3334364C0>,
'index': <function index at 0x000001A333436550>
}
app.view_functions
You can view and operate the view functions registered in the Flask application through access , such as obtaining all endpoint names, obtaining the corresponding view functions, and so on.