登录认证装饰器
# 方法一:使用wraps
from functools import wraps
def login_decorators(func):
@wraps(func)
def inners(*args, **kwargs):
username = session.get("username")
if username:
res = func(*args, **kwargs)
return res
else:
return redirect("/login/")
return inners
@app.route("/")
@login_decorators
def index():
return render_template("index.html", user_dict=USERS)
# 方法二:使用 endpoint属性 endpoint="函数名"
def login_decorators(func):
def inners(*args, **kwargs):
username = session.get("username")
if username:
res = func(*args, **kwargs)
return res
else:
return redirect(url_for("login"))
return inners
@app.route("/", endpoint="index")
@login_decorators
def index():
return render_template("index.html", user_dict=USERS)
总结:
"""
1、只要函数被装饰器装饰以后,所有被装饰的函数就成了inners了
2、只要在路由装饰器上加 endpoint属性 ,就可以解决这个问题
3、endpoint等同于Django 路由中的 name--->给路由起别名---->可以通过反向解析,通过名字找到函数
4、url_for 做路由反向解析---->需要使用到endpoint指定的名字
"""
类装饰器
>类装饰器:1、加在类上面的装饰器。2、类作为装饰器
# 加在类上面的装饰器
def auth(func):
def inner(*args, **kwargs):
response = func(*args, **kwargs) # 现在这个response就是Person的对象
response.name = "彭于晏"
response.age = 33
return response
return inner
@auth # Person=auth(Person)--->以后Person就变成了 inner
class Person:
def __init__(self, name):
self.name = name
p = Person("kevin")
print(p.name) # 彭于晏
print(p.age) # 33
总结:
"""
1、加载类上面的装饰器---->如果装饰器中什么都没写,类用起来跟以前是一样的
2、如果装饰器中对 类的对象 进行了操作,只要加了这个装饰器,所有类产生的对象,都会走装饰器inner内的操作
"""
# 类作为装饰器
模版:
class Auth:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
response = self.func(*args, **kwargs)
return response
实例:
class Auth:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
response = self.func(*args, **kwargs)
return response
@Auth # add = Auth(add)----->后续 add 就是Auth的对象了-->add(1,2)---->Auth类对象(),也就是说现在add函数就成了Auth的对象
def add(a, b):
return a + b
print(add(1, 2)) # add()其实就是Auth对象加(),对象加()就会触发__call__方法的执行
# 类装饰器装饰类
class Auth():
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('我执行了')
res = self.func(*args, **kwargs)
print('执行完了')
return res
@Auth # Person=Auth(Person)
class Person:
pass
p = Person() # Person()---->本质是谁? Auth(Person)()--->触发Auth的__call__
# 1 给类加装饰器--->在装饰器中,可以控制对象的产生过程,以及修改对象(给对象加属性或方法)---->增强了对象
# 2 类作为装饰器---->必须要写 __init__ 和 __call__--->原来装饰器在执行被装饰函数之前或之后的代码,都写在__call__中
# 有参装饰器--->额外为被装饰的函数传参数
# 什么是有参装饰器--->之前的装饰器,都不加括号--->如果有参装饰器,装饰器加括号
# 在装饰器内部,有些动态参数,是通过传参传过来的,就可以使用有参装饰器
def auth(name):
def outter(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
return outter
name='彭于晏'
@auth(name) # add=auth('kevin')(add)
def add(a,b):
return a+b
flask配置使用方式
# 1 方式一:直接在app中修改,只能改以下两个
app.debug=True
app.secret_key='asdfasdf'
# 2 使用py文件方式---》跟django一样
app.config.from_pyfile('./settings.py')
print(app.config) # 就是所有配置信息---》就是django 的 from django.conf import settings
print(app.config.get("DEBUG"))
print(app.config.get("MYSQL_HOST"))
# 3 类的方式--->以后写出多个类,上线和测试完全分开
app.config.from_object('settings.ProductionConfig')
app.config.from_object('settings.DevelopmentConfig')
print(app.config.get('DEBUG'))
print(app.debug) print(app.debug is app.config.get('DEBUG'))
# 4 其他---->了解
app.config.from_envvar("环境变量名称")
环境变量的值为python文件名称名称,内部调用from_pyfile方法
app.config.from_json("json文件名称")
JSON文件名称,必须是json格式,因为内部会执行json.loads
app.config.from_mapping({'DEBUG': True})
# 5 配置中心--->apollo和nacos区别
app.config.from_mapping(config_data)
内置配置
{
'DEBUG': get_debug_flag(default=False), 是否开启Debug模式
'TESTING': False, 是否开启测试模式
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False,
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}
路由系统
1 flask 路由是基于装饰器的
-rule:路径,不能写正则
-methods=['GET','POST] :允许的请求方式
-endpoint: 当前路由的别名--->反向解析用
2、转换器类型:
| `string` | (default) 任意字符串类型,不能带 / |
| `int` | 接收正整数 |
| `float` | accepts positive floating point values|
| `path` | 带 / 的string |
| `uuid` | accepts UUID strings |
3、其他写法:
@app.route("/", methods=["GET", "POST"]) 如果不写methods只能进行GET访问
@app.get
@app.post
4、路由系统本质
-装饰器--->本质是 self.add_url_rule(rule, endpoint, f, **options)
-self是 Flask(__name__) app对象
-自己注册路由,不使用装饰器
app.add_url_rule('/', view_func=index)
app.add_url_rule('/home', view_func=home)
5、其他参数:add_url_rule 本质就是在研究app.route 除了view_func之外的所有参数
1 rule, URL规则
2 view_func, 视图函数名称
3 defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'} 为函数提供参数
4 endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
5 methods = None, 允许的请求方式,如:["GET", "POST"]
6 strict_slashes = None #对URL最后的 / 符号是否严格要求
7 redirect_to = None,#重定向到指定地址
CBV
from flask import Flask
from flask.views import MethodView
app = Flask(__name__)
class LoginView(MethodView):
methods = ["get", "post"] # 允许的请求方式
def get(self):
return "get"
def post(self):
return "post"
# 注册路由
# LoginView.as_view('login') 参数是别名
app.add_url_rule("/login", view_func=LoginView.as_view("login"))
# 2 cbv加装饰器,直接加在视图类的方法上---》第一个参数必须是self,需要额外处理
# 在类中直接写 decorators = [auth] 按之前装饰器的样子用即可
### 3 methods的用法
# methods = ['get', 'post'] # 允许的请求方式
## 4 MethodView继承了View,View中有as_view方法---》本质是执行了dispath_request-->Vie没有写dipatch--》MethodView写了所以,视图类必须要继承MethodView
## 如果非要继承View,匹配方式,需要自己写