一. 路由和响应函数(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. 子域名
- 例如buy.autohome.com.cn/, dealer.autohome.com.cn
- xxxx.com要为真正能使用的域名,如果本地模拟域名访问,可以修改host文件,那就不用经过DNS解析,使xxxx.com指向127.0.0.1
- hosts文件:
- Windows: C:WindowsSystem32driversetchosts
- Unix: /etc/hosts
- 例如在hosts文件里添加
- 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. 自定义正则路由
- 由第五点常见的路由可知,是用Converter实现的
- 所以,我们可以写一个类继承Converter来实现我们的自定义正则路由
- 步骤:
- 写RegexConverter类
- 将RegexConverter添加到flask中
- 访问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()