之前分析route方法的時候,可以看到中間會調用add_url_rule方法,add_url_rule方法和route方法一樣屬於Flask這個類的。
add_url_rule方法主要用來連接url規則。具體工作方法和route類似。如果提供了視圖函數,它將會和endpoint名字一起被注冊
#裝飾器使用方法: @app.route('/') def index(): pass # 等同與下面這種方法: def index(): pass app.add_url_rule('/', 'index', index) If the view_func is not provided you will need to connect the endpoint to a view function like so:: # 如果視圖函數沒有被提供,需要用下面語法把視圖函數和endpoint對應起來 app.view_functions['index'] = index

def add_url_rule(self, rule, endpoint=None, view_func=None, **options): if endpoint is None: endpoint = _endpoint_from_view_func(view_func) options['endpoint'] = endpoint methods = options.pop('methods', None) # if the methods are not given and the view_func object knows its # methods we can use that instead. If neither exists, we go with # a tuple of only ``GET`` as default. if methods is None: methods = getattr(view_func, 'methods', None) or ('GET',) if isinstance(methods, string_types): raise TypeError('Allowed methods have to be iterables of strings, ' 'for example: @app.route(..., methods=["POST"])') methods = set(item.upper() for item in methods) # Methods that should always be added required_methods = set(getattr(view_func, 'required_methods', ())) # starting with Flask 0.8 the view_func object can disable and # force-enable the automatic options handling. provide_automatic_options = getattr(view_func, 'provide_automatic_options', None) if provide_automatic_options is None: if 'OPTIONS' not in methods: provide_automatic_options = True required_methods.add('OPTIONS') else: provide_automatic_options = False # Add the required methods now. methods |= required_methods rule = self.url_rule_class(rule, methods=methods, **options) rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule) 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('View function mapping is overwriting an ' 'existing endpoint function: %s' % endpoint) self.view_functions[endpoint] = view_func
參數解析:
- rule: 一個字符串格式的url規則,如:"/login". 注:就是從route方法中調用add_url_rule是傳遞的rule
- endpoint: url規則的名字,用來反向生成url使用,默認是視圖函數的名字。注:如果是route方法調用的,則這個參數是route方法傳遞過來的endpont
- view_func: 視圖函數,當對應的endpoint名字被請求時需要調用的函數。注:如果時router方法點用的add_url_rule,則這個參數時router方法傳遞過來的f
- options: 類似與分析route時候的options.這個options是跟隨:class:`~werkzeug.routing.Rule` object定義的,后面會分析這個對象中的具體參數,但有一個methods參數默認是只監聽get方法。注:如果是router方法點用的add_url_rule,則這個參數時router方法傳遞過來的options函數
函數體解析:
1 def add_url_rule(self, rule, endpoint=None, view_func=None, **options): 2 if endpoint is None: 3 # 如果沒有提供endpoint參數,則默認用view_func的名字 4 endpoint = _endpoint_from_view_func(view_func) 5 # 把endpoint參數添加到options里面 6 options['endpoint'] = endpoint 7 # 從options中pop出methods參數,並把值賦給methods變量,如果沒有則置為None 8 methods = options.pop('methods', None) 9 # moehods的值為None的情況下 10 if methods is None: 11 # 如果view_func函數中有這個methods參數,則使用view_func中的。如果沒有則賦一個列表('GET',)給methods 12 methods = getattr(view_func, 'methods', None) or ('GET',) 13 # 如果methods是字符串類型 14 if isinstance(methods, string_types): 15 # 拋出一個異常:methods需要是一個可以迭代的字符串 16 raise TypeError('Allowed methods have to be iterables of strings, ' 17 'for example: @app.route(..., methods=["POST"])') 18 # 把methods里面的item都改成大寫 19 methods = set(item.upper() for item in methods) 20 21 # 在view_func里面定義了一個屬性required_methods = () 22 # 作用:用來定義一些必須的方法,配合provide_automatic_options使用 23 required_methods = set(getattr(view_func, 'required_methods', ())) 24 25 # starting with Flask 0.8 the view_func object can disable and 26 # force-enable the automatic options handling. 27 # 在view_func里面定義了一個屬性provide_automatic_options = None 28 # 作用:用於禁用和強制啟用一些自動選項 29 provide_automatic_options = getattr(view_func, 30 'provide_automatic_options', None) 31 32 # 判斷provide_automati_options是否為None 33 if provide_automatic_options is None: 34 # 如果OPTIONS字符串沒有在methods里面 35 if 'OPTIONS' not in methods: 36 # 則把provude_automatic_options改為True,並把OPTIONS添加到required_methods里面 37 provide_automatic_options = True 38 required_methods.add('OPTIONS') 39 # 如果OPTIONS在methods里面,則把provide_automatic_options設置為False 40 else: 41 provide_automatic_options = False 42 43 # 合並required_methods和methods這兩個集合到methods里面 44 methods |= required_methods 45 46 # 創建路由規則 47 # 調用url_rule_class方法,由於在Flask類的全局變量中定義了:url_rule_class = Rule, Rule是werkzeug/routing.py里面的一個類 48 # 也就是相當於實例化了Rule得到了rule對象,具體實例化后的結果請看Rule源碼分析 49 rule = self.url_rule_class(rule, methods=methods, **options) 50 # 把provide_automatic_options屬性添加到rule對象里面 51 rule.provide_automatic_options = provide_automatic_options 52 53 # 在Flask類的__init__里面定義了self.url_map = Map(),Map是werkzeug/routing.py里面的一個類 54 # self.url_map相當與實例化了Map,.add則是調用了Map類里面的add方法 55 # 具體運行結果,請參考Map源碼分析,以及Map源碼中的add方法分析 56 self.url_map.add(rule) 57 # 如果提供了view_func 58 if view_func is not None: 59 # 在flask類的__init__里面定義了self.view_functions = {}, 60 # 從字典里面取endpoint值並賦值為old_func,(endpoint是傳遞的參數,默認為視圖函數名) 61 old_func = self.view_functions.get(endpoint) 62 # 如果old_func有值,並且不等於view_func 63 if old_func is not None and old_func != view_func: 64 # 則拋出異常:視圖函數映射被一個已經存在的函數名重寫了 65 # 也就是說已經存在了一個endpoint:old_func的映射,但是old_fun卻不是view_func,也就是說endpoint重復了 66 raise AssertionError('View function mapping is overwriting an ' 67 'existing endpoint function: %s' % endpoint) 68 # 添加視圖函數與endpoint映射到view_functions字典里面 69 self.view_functions[endpoint] = view_func