cbv分析

视图函数

from flask import Flask, request
from flask.views import View, MethodView

app = Flask(__name__)
app.debug = True


class IndexView(MethodView):
    def get(self):
        print(request.method)
        return 'get请求'

    def post(self):
        print(request.method)
        return 'post请求'


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


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

源码分析

1.
# IndexView.as_view('index')执行完的的结果是父类View中的as_view里面的view函数
def as_view(
        cls, name: str, *class_args, **class_kwargs
    ) -> ft.RouteCallable:
    
    def view(**kwargs: t.Any) -> ft.ResponseReturnValue:
        # 实际上是使用异步执行了self.dispatch_request
        return current_app.ensure_sync(self.dispatch_request)(**kwargs)
     return view
    
2.
# 请求来了执行函数view(),实际上是执行了MethodView中的dispatch_request
    def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
        # self是视图类的对象
        meth = getattr(self, request.method.lower(), None)
        # meth()是使用异步执行的
        return current_app.ensure_sync(meth)(**kwargs)
    
3. 路径如果不传别名,那么就以函数名作为别名
-@app.route('/index')  # 没有传endpoint
    # endpoint 就是None---》调用了app.add_url_rule,传入了None
    if endpoint is None:
        endpoint = _endpoint_from_view_func(view_func)  
        # type: ignore
	# _endpoint_from_view_func 就是返回函数的名字
    
4.as_view('index')必须传参数,传过来的参数是别名
app.add_url_rule('/index',view_func=IndexView.as_view('index'))
在as_view函数中有一个内层的闭包函数view,他里面有一句代码
    view.__name__ = name  # 将函数名修改为我们传入的名字
所以我们就可以简写成
    app.add_url_rule('/index',view_func=view)
# 如果有多个视图函数,都不传参数的话,所有的别名都是内层函数view,会报错,所以在多个视图函数的情况下传入不同的别名

5.我们的视图类必须继承methodView,如果直接继承View,没有dispatch_request,我们就需要自己重写dispatch_request

6.视图类加装饰器,直接在类属性上配置decorators就行了
    decorators = [auth,]
    # 源码,cls是视图类,中有decorators
    if cls.decorators:
      for decorator in cls.decorators:
          view = decorator(view)  # view=auth(view)
            
总结:
    1.as_view的执行流程与django一样
    2.路径如果不传别名,那么别名就是函数名
    3.视图函数加多个装饰器,必须传endpoint,还需要注意装饰器的顺序
    4.视图类必须继承MethodView,否则重写dispatch_request
    5.视图类加装饰器:类属性decorators = [auth,]

模板

from flask import Flask, render_template, Markup

app = Flask(__name__, template_folder='templates', static_folder='static')
app.debug = True


def add(a, b):
    return a + b


@app.route('/')
def index():
    a = '<a href="http://www.baidu.com">点击</a>'
    a = Markup(a)
    return render_template('index.html', name='zyg', a=a, add=add)


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

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<h1>模板语法,if</h1>
{% if name %}
<h1>Hello {{ name }}</h1>
{% else %}
<h1>ByeBye</h1>
{% endif %}

<h1>模板语法,标签渲染</h1>
{{ a|safe }}
{{ a }}

<h1>模板语法,执行函数</h1>
{{ add(11,22) }}
</body>
</html>

请求与响应

from flask import Flask, request, make_response, render_template

app = Flask(__name__)
app.debug = True

@app.route('/', methods=['GET', 'POST'])
def index():
    # 请求
    print(request.method)
    print(request.args)
    print(request.form)
    print(request.values)
    print(request.cookies)
    print(request.headers)
    print(request.path)
    print(request.full_path)
    print(request.url)
    print(request.base_url)
    print(request.host_url)
    print(request.host)
    obj = request.files['file']
    obj.save(obj.filename)
    # 响应头中写数据都用make_response包一下
    response = render_template('index.html')
    res = make_response(response)
    res.headers['yy'] = 'yy'
    
if __name__ == '__main__':
    app.run()
    
总结:
    request.method          提交的方法
    request.args            get请求提及的数据
    request.form            post请求提交的数据
    request.values          post和get提交的数据总和
    request.cookies         客户端所带的cookie
    request.headers         请求头
    request.path            不带域名,请求路径
    request.full_path       不带域名,带参数的请求路径
    request.url             带域名带参数的请求路径
    request.base_url        带域名请求路径
    request.url_root        域名
    request.host_url        域名
    request.host            127.0.0.1:500

session及源码分析

session的使用

from flask import Flask, request, session, render_template, redirect


app = Flask(__name__)
app.debug = True
app.secret_key = 'sfdregxdfgdfsshsdcvasdfsa'


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        name = request.form.get('name')
        password = request.form.get('password')
        session['name'] = name
        return redirect('/index')


@app.route('/index', methods=['GET', 'POST'])
def index():
    return 'hello %s' % session.get('name', '匿名用户')


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

源码分析

cookie是放在客户端浏览器中的键值对
session在diango中是放在服务端的键值对,django中放在了django_session表中
在flask中session则是加密后放在了cookie中

源码:
    1.app.session_interface 配置了一个类的对象,它是session的执行流程
    2.类中有两个方法,请求来的时候会执行open_session,请求走的时候会执行save_session
        def open_session(self, app, request):
            # 根据名字取出前端传入的cookie的value值
            val = request.cookies.get(self.get_cookie_name(app))
            # 如果没有val,则是构造了一个空的session对象
            if not val:
                return self.session_class()
            max_age = int(app.permanent_session_lifetime.total_seconds())
        try:
            # 如果没有过期,解码,做成session对象,后续直接用session即可
            data = s.loads(val, max_age=max_age)
            return self.session_class(data)
        except BadSignature:
            # 如果过期了,也是空session
            return self.session_class()
        
        def save_session(self, app, session, response):
            name = self.get_cookie_name(app)
            # 取出过期事件,把它和session一起加密转成字符串放到cookie中
            expires = self.get_expiration_time(app, session)
        	val = self.get_signing_serializer(app).dumps(dict(session))
        	response.set_cookie(
            	name,
            	val, 
            	expires=expires,
        )

闪现

其实就是flash
它其实就是当次请求先把一些数据放在某个位置,然后下一次请求净这些数据取出来,数据取出来以后就没了,不能再次取用,相当于一次性存储
flash作用
    1.可以跨请传递数据或保存数据
    2.当次请求错误重定向到其他地址,可以拿到当时的错误
    
用法:
     设置
         1.flash(),可以设置多次放到一个列表中
         2.flash(category='debug')  分类存
     获取
         1.get_flashed_messages()  取完就删除
         2.get_flashed_messages(category_filter=['debug'])  分类取

请求扩展

类似于django的中间件,请求来的时候或走的时候可以绑定一些函数,到这里就会触发执行对应的函数
flask中就用请求扩展来代替django中的中间件

请求扩展分类:
    1.before_request  请求来的时候会走,如果返回的是四件套就结束
    # 请求来的时候是从上往下执行
    2.after_request  请求走的时候会走,返回response对象
    # 请求走的时候是从下往上执行
    3.before_first_request  请求第一次来会走,之后就不走了
    4.teardown_request  无论是否出异常都会走,通常用来做错误日志
    5.errorhandler  监听状态码,通常用来做统一异常处理
    6.template_global:标签
    7.template_filter:过滤器
posted on 2023-04-07 21:23  zyg111  阅读(20)  评论(0编辑  收藏  举报