CBV源码
https://flask.palletsprojects.com/en/3.0.x/views/ ##1 cbv源码执行流程 # 执行流程 ''' 1 请求来了,路由匹配成功---》执行ItemAPI.as_view('item')()--->view加括号执行 2 ItemAPI.as_view('item')执行结果:就是View中as_view方法中的闭包函数 view 3 view()--->执行self.dispatch_request()---》执行MethodView的dispatch_request def dispatch_request(self, **kwargs): meth = getattr(self, request.method.lower(), None) return meth(**kwargs) 4 如果是get请求,就会执行视图类中的get方法 class View: @classmethod def as_view() def view(): self.dispatch_request() return view ''' ##2 endpoint 的使用 app.add_url_rule('/item', endpoint='xxx',view_func=ItemAPI.as_view('item')) 如果写了endpoint---》别名以它为准,如果不写以as_view的参数为准 ## 逻辑: 1 app.add_url_rule('/item',endpoint='xxx', view_func=ItemAPI.as_view('item')) 2 endpoint = _endpoint_from_view_func(view_func) 如果endpoint没传,就会走这句 view_func 是 ItemAPI.as_view('item') 它就是 view 3 _endpoint_from_view_func(view_func)---》返回了传入的函数的名字 return view_func.__name__ 4 如果上面传入了ItemAPI.as_view('item'),它的函数名就是view---》endpoint就是view ## 总结: endpoint如果不传,会以视图函数的函数名作为endpoint -fbv:如果不写endpoint,会以函数名作为endpoint,但是如果多个视图函数加了同一个装饰器,又没有指定endpoint,就会出错了 -cbv:调用as_view一定要传入一个字符串---》如果endpoint没写,endpoint就是传入的这个字符串,如果写了,这个字符串没用 如果传了,直接以endpoint传入的作为endpoint ### cbv中加装饰器 1 使用步骤:在类中加入类属性: class ItemAPI(MethodView): decorators = [装饰器,装饰器2] def get(self): # print(url_for('xxx')) print(url_for('item')) return 'get' 2 if cls.decorators: for decorator in cls.decorators: view = decorator(view) ''' @装饰器 def view() '''
整个CBV执行流程
# View的as_view @classmethod def as_view(cls, name, *class_args, **class_kwargs) : def view(**kwargs): return self.dispatch_request(**kwargs) if cls.decorators: # 咱们的装饰器 for decorator in cls.decorators: #每次拿出一个装饰器, view = decorator(view) # 装饰器语法糖干的事: 把被装饰的函数当参数传入到装饰器,返回结果赋值给被装饰的函数,一个个用装饰器包装view view.__name__ = name return view # self.dispatch_request---》MethodView def dispatch_request(self, **kwargs) : # 取到request.method.lower()请求方式小写 ---》假设是get请求get # meth是 cbv中 以get命名的方法,反射出来了 meth = getattr(self, request.method.lower(), None) return meth(**kwargs) # 执行cbv中跟请求方式同名的方法
def register_api(app, model, name): item = ItemAPI.as_view(f"{name}-item", model) group = GroupAPI.as_view(f"{name}-group", model) app.add_url_rule(f"/{name}/<int:id>", view_func=item) # get put delete app.add_url_rule(f"/{name}/", view_func=group) #post get register_api(app, User, "users") register_api(app, Story, "stories")
模版
# flask使用了Jinja,flask提供了文档,也可以去Jinja官网看 https://flask.palletsprojects.com/en/3.0.x/ https://jinja.palletsprojects.com/en/3.1.x/ # 总结:之前学过dtl -{{变量/简单表达式/函数}} -{%if/for %} {%endif%} {%endfor%} -比dtl强大 ,Jinja中可以加括号 -字典取值,列表取值跟python语言一样,之前dtl 通过 .取值 -过滤器,标签 -extends,include 跟之前一样
请求响应
# 所有web:请求对象,响应对象(go,java,ptyhon) django:request(每个请求一个request),新手四件套 flask: requset:全局的,但是也是每个请求一个request,新手三件套 # request 全局对象,用起来,跟之前django的一样 # 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 服务端地址 # request.files # obj = request.files['the_file_name'] # obj.save('/var/www/uploads/' + secure_filename(f.filename)) # 响应 response---》四件套 -return '字符串' -return render_template('index.html',name=lqz,age=19) -return redirect(url_for(别名)) -return jsonify(字典,列表) # 往cookie中写数据--->四件套需要使用 obj=make_response('index') obj.set_cookies() # 跟之前一样 # obj.headers[]
session
# cookie 机制 # 设置 obj=make_response('index') obj.set_cookies('name','lqz') # 取 request.cookie.get('name') # session机制 1 设置秘钥 2 写入session session['username']='xxx' 3 取出session username = session.get('username')