一、Flask的CBV
1.CBV的写法
from flask import Flask
app = Flask(__name__)
app.debug = True
@app.route('/')
def index():
return 'hello'
from flask.views import MethodView
class TestView(MethodView):
def get(self):
return '我是get'
def post(self):
return '我是post'
app.add_url_rule('/test', 'test', TestView.as_view('test'))
if __name__ == '__main__':
app.run()

2.CBV的执行流程
'从上面CBV的写法来查看执行流程'
1.app.add_url_rule('/test', 'test', TestView.as_view('test'))
-这个注册路由的第三个参数,放视图函数的内存地址,也就是TestView.as_view('test') 是函数内存地址
2.所以我们需要在TestView中找类的方法as_view
-已知我们自己写的TestView中没有写这个方法,所以得去继承的MethodView中寻找,最后在MethodView继承的View中找到了
@classmethod '把源码精简一下'
def as_view(cls, name,*class_args, **class_kwargs):
def view(**kwargs):
'这里是把它放到异步函数中操作,本质就是return了self.dispatch_request(**kwargs)'
return current_app.ensure_sync(self.dispatch_request)(**kwargs)
return view
3.app.add_url_rule的第三个位置,也就是as_view,放的就是View的内层函数
4.当请求来了的时候,路由匹配成功,就会执行view(参数),本质上就是执行self.dispatch_request(**kwargs)
5.所以我们要去找dispatch_request方法,我们视图类中没有,那么去父类MethodView中寻找,结果找到了
'这个就跟我们Django中的CBV一样了'
'然后看到self.dispatch_request中方法 ,在当前视图类中反射,请求方式的小写字符串(get,post),如果我们写了这些方法 就会去执行。'
def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
meth = getattr(self, request.method.lower(), None)
if meth is None and request.method == "HEAD":
meth = getattr(self, "get", None)
assert meth is not None, f"Unimplemented method {
request.method!r}"
return meth(**kwargs)
3.endpoint 的使用
1.如果写了endpoint,别名以它为准,如果不写以as_view的参数为准
app.add_url_rule('/test', endpoint='xxx',view_func=TestView.as_view('test'))
'逻辑:'
1 app.add_url_rule('/test',endpoint='xxx', view_func=TestView.as_view('test'))
2 endpoint = _endpoint_from_view_func(view_func)
如果endpoint没传也就是None,就会走这句 view_func是TestView.as_view('test') 它就是函数名
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options["endpoint"] = endpoint
3 _endpoint_from_view_func(view_func)---》返回了传入的函数的名字
return view_func.__name__
4 如果上面传入了TestView.as_view('test'),它的函数名就是view---》endpoint就是view
-view.__name__ = name
-view的名字 是咱么 TestView.as_view('名字') 传入的名字,不再是view了
'总结:'
endpoint如果不传,会以视图函数的函数名作为endpoint
-fbv:如果不写endpoint,会以函数名作为endpoint,但是如果多个视图函数加了同一个装饰器,又没有指定endpoint,就会出错了
-cbv:调用as_view一定要传入一个字符串---》如果endpoint没写,endpoint就是传入的这个字符串,如果写了,这个字符串没用
如果传了,直接以endpoint传入的作为endpoint
TestView.as_view(name='index'),name到底有啥用
app.add_url_rule('/test', view_func=TestView.as_view('test'))
没有传endpoint,Login.as_view('login')是view函数的内存地址
endpoint会以函数名作为endpoint的值,现在所有函数都是view,必须传入name,来修改调view函数的名字
如果传了endpoint,别名以endpoint为主,如果不传endpoint,别名以name为主
app.add_url_rule('/test', view_func=TestView.as_view(name='test'),endpoint='xxx')
4.CBV中得methods作用
视图类中有个属性就是methods = ['GET', 'POST']
用来控制允许的请求方式 写了什么方法 就允许什么请求 若没有写则不能使用该方法
5.CBV加装饰器
1 使用步骤:在类中加入类属性:
class UserView(MethodView):
decorators = [装饰器1,装饰器2]
def get(self):
return 'get'
def post(self):
return 'post'
2.我们在as_view源码中可以看到
if cls.decorators:
view.__name__ = name
view.__module__ = cls.__module__
'循环拿出,然后使用装饰器来执行被装饰函数,然后在把执行的赋值给被装饰函数'
for decorator in cls.decorators:
view = decorator(view)
二、模版语法
1.渲染变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户列表</h1>
<table>
{
% for k,v in user_dict.items() %}
<tr>
<td>{
{
k}}</td>
<td>{
{
v.name}}</td>
<td>{
{
v['name']}}</td>
<td>{
{
v.get('name')}}</td>
<td><a href="/detail/{
{k}}">查看详细</a></td>
</tr>
{
% endfor %}
</table>
</body>
</html>
2.变量的循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户列表</h1>
<table>
{
% for k,v