# 0 装饰器的本质原理
-# 类装饰器:1 装饰类的装饰器 2 类作为装饰器
# 1 装饰器使用位置,顺序
# 3 flask路由下加装饰器,一定要加endpoint
-如果不指定endpoint,反向解析的名字都是函数名,不加装饰器没有问题,就是正常函数index,detail
-如果加了装饰器---》index,detail都变成了inner---》反向解析的名字都是函数名inner,报错了
-wrapper装饰器----》把它包的更像---》函数名变成了原来函数的函数名
def add(func):
print(func)
# 类装饰器:1 装饰类的装饰器 2 类作为装饰器
# add 一定是个函数吗?
# 放个对象
class Person:
def __call__(self, func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
p = Person()
# @add # test=add(test)--->test变成了None
@p # test=p(test) # p() 会触发__call__--->Person的 __call__(func)--->返回inner,以后test就是inner---》test(参数)--》执行的是inner
def test():
print("test")
print(test)
def auth(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs) # 真正的执行视图函数,执行视图函数之,判断是否登录
res.name='lqz'
return res
return inner
@auth # Foo=auth(Foo)
class Foo():
pass
f=Foo() # Foo() 调用 ---》inner()--->类实例化得到对象,返回,以后f就是Foo的对象,但是可以里面多了属性或方法
print(f)
print(f.name)
### 有参装饰器--->额外为被装饰的函数传参数
@auth(10) # Foo=auth(10)(Foo)
class Foo():
pass
PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
app.config['DEBUG'] = True
#通过py文件配置
app.config.from_pyfile("python文件名称")
如:
settings.py
DEBUG = True
app.config.from_pyfile("settings.py")
#通过环境变量配置
app.config.from_envvar("环境变量名称")
#app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])
环境变量的值为python文件名称名称,内部调用from_pyfile方法
# JSON文件名称,必须是json格式,因为内部会执行json.loads
app.config.from_json("json文件名称")
# 字典格式
app.config.from_mapping({'DEBUG': True})
# 对象
app.config.from_object("python类或类的路径")
app.config.from_object('pro_flask.settings.TestingConfig')
settings.py
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite://:memory:'
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
PS: 从sys.path中已经存在路径开始写
PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录(Flask对象init方法的参数)
# 1 flask路由系统是基于装饰器的:参数如下
# 2 转换器:
# 3 路由系统本质
# 4 endpoint 不传会怎么样,不传会以视图函数的名字作为值,但是如果加了装饰器,所有视图函数名字都是inner,就会出错,使用wrapper装饰器再装饰装饰器
from flask import Flask
app = Flask(__name__)
# 1 flask路由系统是基于装饰器的:参数如下
# rule:路径
# methods :请求方式,列表
# endpoint: 路径别名
# 2 转换器:
''' string int path
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
'''
## 3 路由系统本质-->读源码
'''
def decorator(f: T_route) -> T_route:
endpoint = options.pop("endpoint", None) #从options弹出,如果没有,就是None ---》@app.route(传了就有,不传就是None)
self.add_url_rule(rule, endpoint, f, **options)
return f # f 就是视图函数,没有对视图函数做事情,只是在执行视图函数之前,加了点操作
核心:self.add_url_rule(rule, endpoint, f, **options)---》self就是app对象
app.add_url_rule('路由地址', '路由别名', 视图函数, **options)--->跟django很像
add_url_rule的参数详解
rule, URL规则,路径地址
view_func, 视图函数名称
defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}
为函数提供参数
endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
methods = None, 允许的请求方式,如:["GET", "POST"]
#对URL最后的 / 符号是否严格要求
strict_slashes = None
#重定向到指定地址
redirect_to = None,
'''
'''
4 endpoint 不传会怎么样,不传会以视图函数的名字作为值,但是如果加了装饰器,所有视图函数名字都是inner,就会出错,使用wrapper装饰器再装饰装饰器
'''
## 4
# @app.route('/detail/',methods=['GET'],endpoint='detail')
# @app.route('/', methods=['GET'])
@app.route('/', methods=['GET']) # index=app.route('/', methods=['GET'])(index)--->index=decorator(index)
def index(name):
print(name)
return 'hello world'
def home():
return 'home'
# app.add_url_rule('/', 'index', index,defaults={'name':'lqz'})
# app.add_url_rule('/home', 'home', home,strict_slashes=True,redirect_to = '/')
if __name__ == '__main__':
app.run()