Flask - 路由

一. 路由和响应函数(View function)的映射是通过装饰器实现的

1.

"""
#装饰器:
def wrapper(func):
    def inner(*args, **kwargs):
        return func(*args, **kwargs)
    return inner


@wrapper 相当于 index = wrapper(index)
def index(request):
    pass
"""

# app.route('path')将view function注册到一个类似于字典的数据结构中,从而实现路由和响应函数的映射。
url_map = {
    '/index': index
}


def route(option):  # {'k1':'v1'}
    def inner(func, *args, **kwargs):
        url_map[option['path']] = func

    return inner


# inner = wrapper({'k1':'v1'})
# @inner --> inner(index)
@route({'path': '/index'})
def index(request):
    pass

2. app.route源码

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

3. app.route自我理解

"""
1. decorator = app.route('/',methods=['GET','POST'],endpoint='n1')
    def route(self, rule, **options):
        # app对象
        # rule= /
        # options = {methods=['GET','POST'],endpoint='n1'}
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options) #添加路由的本质!!!!!!!!!
            return f
        return decorator
2. @decorator
    decorator(index)
"""
@app.route('/',methods=['GET','POST'],endpoint='n1')
def index():
    return 'Hello World!'

4. 不通过装饰器添加路由,手动添加路由

知道了app.route()里面的self.add_url_rule是本质,所以自己可以手动调用这个方法添加路由

def login():
    return '登录'

app.add_url_rule('/login', 'n2', login, methods=['GET',"POST"])

5. 常用的路由系统

@app.route('/user/<username>')
@app.route('/post/<int:post_id>')
@app.route('/post/<float:post_id>')
@app.route('/post/<path:path>')
@app.route('/login', methods=['GET', 'POST'])
DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

6. 还可以用CBV(class bsae view)添加路由,和Django一样,留坑。

from flask import Flask,views

app = Flask(__name__)
app.debug = True
app.secret_key = "asdfasdf"


def auth(func):
    def inner(*args, **kwargs):
        result = func(*args, **kwargs)
        return result
    return inner

class IndexView(views.MethodView):
    methods = ['GET']
    decorators = [auth, ]

    def get(self):
        return 'Index.GET'

    def post(self):
        return 'Index.POST'

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint


if __name__ == '__main__':
    app.run()

from flask import views

"""
    flask.views
    ~~~~~~~~~~~

    This module provides class-based views inspired by the ones in Django.

    :copyright: © 2010 by the Pallets team.
    :license: BSD, see LICENSE for more details.
"""

7. 访问旧的URL时,重定向到新的URL

> 1. 前端HTML的meta, JS也可以实现重定向
> 2. 后台的redirect_to参数可以实现重定向
from flask import Flask

app = Flask(__name__)
app.debug = True

@app.route('/index',methods=['GET','POST'],endpoint='n1',redirect_to="/index2")
def index():
    return '旧首页'


@app.route('/index2',methods=['GET','POST'],endpoint='n2')
def index2():
    return '新首页'


if __name__ == '__main__':
    app.run()

8. 子域名

  1. 例如buy.autohome.com.cn/, dealer.autohome.com.cn
  2. xxxx.com要为真正能使用的域名,如果本地模拟域名访问,可以修改host文件,那就不用经过DNS解析,使xxxx.com指向127.0.0.1
  3. hosts文件:
  4. Windows: C:\Windows\System32\drivers\etc\hosts
  5. Unix: /etc/hosts
  6. 例如在hosts文件里添加
  7. 127.0.0.1 xxxx.com 127.0.0.1 admin.xxxx.com 127.0.0.1 mall.xxxx.com之后才能在浏览器访问
from flask import Flask, views, url_for

app = Flask(import_name=__name__)
# 一定要写域名,不要写IP
app.config['SERVER_NAME'] = 'xxxx.com:5000'


# admin.xxxx.com:5000
@app.route("/", subdomain="admin")
def static_index():
    """Flask supports static subdomains
    This is available at static.your-domain.tld"""
    return "xxxxxx.your-domain.tld"

# buy.xxxx.com:5000
# mall.xxxx.com:5000
@app.route("/dynamic", subdomain="<username>")
def username_index(username):
    """Dynamic subdomains are also supported
    Try going to user1.your-domain.tld/dynamic"""
    return username + ".your-domain.tld"

if __name__ == '__main__':
    app.run()

9. 自定义正则路由

  1. 由第五点常见的路由可知,是用Converter实现的
  2. 所以,我们可以写一个类继承Converter来实现我们的自定义正则路由
  3. 步骤:
  4. 写RegexConverter类
  5. 将RegexConverter添加到flask中
  6. 访问http://127.0.0.1:5000/index/sa失败,访问http://127.0.0.1:5000/index/123成功
from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter

app = Flask(import_name=__name__)


# 1. 写RegexConverter类
class RegexConverter(BaseConverter):
    """
    自定义URL匹配正则表达式
    """

    def __init__(self, map, regex):
        super(RegexConverter, self).__init__(map)
        self.regex = regex

    def to_python(self, value):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        :param value:
        :return:
        """
        # "123" -> 123
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        :param value:
        :return:
        """
        val = super(RegexConverter, self).to_url(value)
        return val


# 2. 将RegexConverter添加到flask中
app.url_map.converters['regex'] = RegexConverter


# 访问http://127.0.0.1:5000/index/sa失败,访问http://127.0.0.1:5000/index/123成功
@app.route('/index/<regex("\d+"):nid>') #这里,先执行to_python去处理nid, nid就是regex('xxxxx'),此处to_python把传入的value变为int
def index(nid):
    print(nid,type(nid))

    url_for('index',nid=89)
    return 'Index'


if __name__ == '__main__':
    app.run()
posted @ 2018-05-08 15:08  Rocin  阅读(200)  评论(0编辑  收藏  举报