装饰器的使用、配置使用、路由系统、CBV

发布时间 2023-11-27 21:06:38作者: Way*yy

登录认证装饰器

# 方法一:使用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,匹配方式,需要自己写