• 四、添加路由的两种方式


    在Flask中,添加路由有两种方式:(一般情况下都是用第一种方式)

    第一种:常见的装饰器模式

    @app.route("/")
    def index():
        return "Hello World"

    通过这种方式,将rule与视图函数对应起来

    第二种:通过阅读装饰器模式添加路由的源码发现

    def route(self, rule, **options):
        """A decorator that is used to register a view function for a
        given URL rule.  This does the same thing as :meth:`add_url_rule`
        but is intended for decorator usage::
    
            @app.route('/')
            def index():
                return 'Hello World'
    
        For more information refer to :ref:`url-route-registrations`.
    
        :param rule: the URL rule as string
        :param endpoint: the endpoint for the registered URL rule.  Flask
                         itself assumes the name of the view function as
                         endpoint
        :param options: the options to be forwarded to the underlying
                        :class:`~werkzeug.routing.Rule` object.  A change
                        to Werkzeug is handling of method options.  methods
                        is a list of methods this rule should be limited
                        to (``GET``, ``POST`` etc.).  By default a rule
                        just listens for ``GET`` (and implicitly ``HEAD``).
                        Starting with Flask 0.6, ``OPTIONS`` is implicitly
                        added and handled by the standard request handling.
        """
    
        def decorator(f):
            endpoint = options.pop("endpoint", None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
    
        return decorator

    是通过self.add_url_rule这个方式建立起rule与视图函数的对应关系的,所以可以这样添加,

    def home():
        return "Hello, home!"
    
    
    app.add_url_rule("/home", endpoint=None, view_func=home)

    endpoint:给rule起一个别名,相当于django path路由函数中的name。

    如何使用通过别名(endpoint)找到rule呢?(如果不起别名,就默认为函数名)

    @app.route("/", endpoint="index")
    def index():
        return "Hello World"
    
    
    def home():
        from flask import url_for
        r = url_for("index")
        # /
        print(r)
        return "Hello, home!"

    ===================================================================================================================================

    如何通过路由传递参数呢?<转换器:参数名>

    @app.route("/<int:uid>/", endpoint="index")
    def index(uid):
        return "Hello {}".format(uid)

    常用的转换器:int、float、path、uuid、string、any、default

    不难发现,没有正则表达式的转换器,那么我们可以自定义:

     1 class RegexConverter(BaseConverter):
     2     def __init__(self, map, regex):
     3         super(RegexConverter, self).__init__(map)
     4         # 为什么只用赋值regex就可以了呢?其他转化器是在类属性regex(正则表达式)的基础上实现的
     5         self.regex = regex
     6 
     7     def to_python(self, value):
     8         """将提取后的值进行处理"""
     9         return value
    10 
    11     def to_url(self, value):
    12         """用于反向解析url"""
    13         val = super(RegexConverter, self).to_url(value)
    14         return val
    15 
    16 
    17 # 虽然我们已经定制好了正则转换器类,但是应用程序不知道,我们还要通知一下
    18 app.url_map.converters["regex"] = RegexConverter
    19 
    20 
    21 @app.route('/<regex("d+"):uid>/', endpoint="index")
    22 def index(uid):
    23     return "Hello {}".format(uid)

    如何rule里面通过路由传参,那如何反向解析呢?

    1 url_for(endpoint, **values)

    参数通过**values传递:url_for(endpoint="index", uuid=10)

    ===================================================================================================================================

    app.route方法常见的参数:

    rule:URL规则

    view_func:视图函数的名称

    default:默认值,当URL中无参数,函数需要参数时,使用default={'k':'v'}为函数提供参数

    endpoint:名称,用于反向生产URL,即:url_for('名称')

    strict_slashes=None:对URL最后的/符号是否严格要求

    redirect_to=None:重定向到指定地址

    subdomain=None:子域名访问

    ==================================================================================================================================

    路由重点:url、methods、endpoint、int转换器、url_for

    ==================================================================================================================================

    如何给视图函数添加装饰器?

    装饰器要放在app.route的下面(放在上面,只会执行一次),并且必须要保留被装饰函数的元信息,因为当我们使用一个装饰器去装饰多个函数时,不保留被装饰函数的元信息,endpoint会默认为函数名,这样就会都等于装饰器函数内部被返回的函数名,导致endpoint重名,会出现错误

     1 def showtime(func):
     2     def inner(uid):
     3         import time
     4         print(time.localtime())
     5         res = func(uid)
     6         print(time.localtime())
     7         return res
     8     return inner
     9 
    10 
    11 @app.route('/<regex("d+"):uid>/', endpoint="index")
    12 @showtime
    13 def index(uid):
    14     return "Hello {}".format(uid)

    为了保留被装饰函数的元信息,必须使用

     1 from functools import wraps
     2 
     3 
     4 def showtime(func):
     5     @wraps(func)
     6     def inner(uid):
     7         import time
     8         print(time.localtime())
     9         res = func(uid)
    10         print(time.localtime())
    11         return res
    12     return inner
    13 
    14 
    15 @app.route('/<regex("d+"):uid>/', endpoint="index")
    16 @showtime
    17 def index(uid):
    18     return "Hello {}".format(uid)
  • 相关阅读:
    Silverlight Toolkit ListBoxDragDropTarget学习笔记
    函数指针和指针函数(转)
    面试题_反转链表
    C++中的异或运算符^
    面试题_旋转字符串
    面试题_寻找丑数
    模拟一个简单的基于tcp的远程关机程序
    管理指针成员
    赫夫曼树编码问题
    堆的基本操作
  • 原文地址:https://www.cnblogs.com/loveprogramme/p/13368483.html
Copyright © 2020-2023  润新知