20标准类视图、基于调度方法的类视图、使用装饰器的类视图

 一:标准类视图:https://www.bilibili.com/video/av62010252/?p=36

1, 标准类视图:必须继承自 views.View(from flask import Flask,views)

2,必须实现dispatch_request(self)方法,以后请求过来后,都会执行这个方法,这个方法的返回值就相当于是之前的函数视图一样。也必须返回“”Response“。”

3,必须通过

“app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))”

来做URL与类视图的映射,‘’view_func‘’这个参数,需要使用类视图下的“as_view”类方法转换:

4,如果指定了endpoint,那么使用url_for时候就必须使用它。如果没有指定,那么默认为类视图名字。

代码示例:

 1 from flask import Flask,views
 2 
 3 app = Flask(__name__)
 4 
 5 class ListView(views.View):
 6     def dispatch_request(self):
 7         return "list view"
 8 
 9 app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))
10 
11 
12 @app.route('/')
13 def hello_world():
14     return 'Hello World!'
15 
16 
17 if __name__ == '__main__':
18     app.run()
 

 那么,为什么我们为什么有函数视图还要用类视图呢?首先,因为类比函数要功能多,封装性也更强。封装性在多次调用时候体现。

示例:

加入有几个URL需要返回json数据,那么:

 1 from flask import Flask,views,jsonify,render_template
 2 
 3 app = Flask(__name__)
 4 
 5 
 6 #加入有几个URL需要返回json数据
 7 class JsonView(views.View):
 8     def get_data(self):
 9         raise NotImplementedError
10     def dispatch_request(self):
11         return jsonify(self.get_data())
12 
13 class ListView(JsonView):
14     def get_data(self):
15         return {'username':'zy','password':'123'}
16 app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))
17 
18 
19 #有几个视图,需要返回相同的变量
20 class ADSView(views.View):
21     def __init__(self):
22         super(ADSView, self).__init__()
23         self.content = {
24             'ads':'This is ads!'
25         }
26 
27 class LoginView(ADSView):
28     def dispatch_request(self):
29         self.content.update({
30             'user': 'zy'
31         })
32         return render_template('login.html',**self.content)
33 
34 class RegistView(ADSView):
35     def dispatch_request(self):
36         return render_template('regist.html',**self.content)
37 app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
38 app.add_url_rule('/regist/',view_func=RegistView.as_view('regist'))
39 
40 
41 @app.route('/')
42 def hello_world():
43     return 'Hello World!'
44 
45 
46 if __name__ == '__main__':
47     app.run()

详细解释:
行16中URL输入http://127.0.0.1:5000/list/时,视图函数会调用类视图ListView,而类视图中必须要有dispatch_request(self),可是这个ListView是子视图,没有这个函数,
这时候需要调用上层的父类JsonView,由其调用dispatch_request(self)函数,执行jsonify(self.get_data())代码,因为是子类调用它,所以这个jsonify(self.get_data())
中的self就为子类本身,即调用子类中的get_data()函数。
那么为什么父类中还有get_data函数呢,它也没啥用?因
为JsonView是不能直接用的,他只是一个抽象的,并不能当做实际视图来用,所以他下面的get_data也不能用,因此用raise。
 
login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登陆页面广告</h1>
{{ ads }} === {{ user }}
</body>
</html>

 

 

类视图有以下好处:

可以继承,把一些共性的东西抽取出来放在父视图中,子视图直接拿来用就可以了,与函数视图对比那个方便就用哪个。

 

二,基于调度方法的类视图 https://www.bilibili.com/video/av62010252/?p=36

先贴一段代码:

 1 from flask import Flask,views,render_template,request
 2 
 3 app = Flask(__name__)
 4 
 5 
 6 @app.route('/')
 7 def hello_world():
 8     return 'Hello World!'
 9 
10 class LoginView(views.MethodView):
11     def get(self):
12         return render_template('login.html')
13     def post(self):
14         username = request.form.get('name')
15         if username == 'zy':
16             return 'Login success'
17         else:
18             return 'faied'
19 
20 app.add_url_rule('/login/',endpoint='login',view_func=LoginView.as_view('list'))
21 
22 if __name__ == '__main__':
23     app.run()

注意:基于调度方法的类视图是MethodView,而非View。

如果我们要加上错误后的提示信息应该怎么加呢?

 1 from flask import Flask,views,render_template,request
 2 
 3 app = Flask(__name__)
 4 
 5 
 6 @app.route('/')
 7 def hello_world():
 8     return 'Hello World!'
 9 
10 class LoginView(views.MethodView):
11     def __geterror(self,error):
12         return render_template('login.html',error=error)
13     def get(self):
14         return render_template('login.html')
15     def post(self):
16         username = request.form.get('name')
17         if username == 'zy':
18             return 'Login success'
19         else:
20             return self.__geterror(error='密码或账户错误')
21 
22 app.add_url_rule('/login/',endpoint='login',view_func=LoginView.as_view('list'))
23 
24 if __name__ == '__main__':
25     app.run()

三,使用装饰器的类视图 

普通使用装饰器的函数视图,代码:

 1 from flask import Flask,request,render_template
 2 from functools import wraps
 3 app = Flask(__name__)
 4 
 5 
 6 @app.route('/')
 7 def hello_world():
 8     return 'Hello World!'
 9 
10 def login_required(func):
11     @wraps(func)   #这里为什么要加这个呢?因为为了防止func函数的属性丢失。
12     def wrapper(*args,**kwargs):
13         user = request.args.get('user')
14         #这里是arg,所以应该写为/set/?user=zy
15         if user and user == 'zy':
16             return func(*args,**kwargs)
17         else:
18             return '请先登录'
19     return wrapper
20 
21 @app.route('/set/')
22 @login_required
23 def set():
24     return '这里是设置界面'
25 
26 
27 
28 
29 if __name__ == '__main__':
30     app.run()

那么使用装饰器的类方法的实现怎么弄呢?

 1 from flask import Flask,request,render_template
 2 from functools import wraps
 3 app = Flask(__name__)
 4 
 5 
 6 @app.route('/')
 7 def hello_world():
 8     return 'Hello World!'
 9 
10 def login_required(func):
11     @wraps(func)   #这里为什么要加这个呢?因为为了防止func函数的属性丢失。
12     def wrapper(*args,**kwargs):
13         user = request.args.get('user')
14         #这里是arg,所以应该写为/set/?user=zy
15         if user and user == 'zy':
16             return func(*args,**kwargs)
17         else:
18             return '请先登录'
19     return wrapper
20 
21 @app.route('/set/')
22 @login_required
23 def set():
24     return '这里是设置界面'
25 
26 from  flask import views
27 class ProfileView(views.View):
28     decorators = [login_required]  #直接这样就行了,不用打括号
29     def dispatch_request(self):
30         return '这里是设置界面'
31 app.add_url_rule('/pro/',endpoint='profile',view_func=ProfileView.as_view('profile'))
32 
33 
34 
35 
36 
37 if __name__ == '__main__':
38     app.run()

 

 

 

 

 

 

 

 

posted @ 2019-08-12 21:58  puppet洛洛  阅读(259)  评论(0编辑  收藏  举报