zoukankan      html  css  js  c++  java
  • 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()
     
  • 相关阅读:
    贪心[2019.5.25]
    顺序统计算法[2019.5.25]
    polya/burnside 学习
    虚拟机上装uoj
    一些常用的数据结构维护手法
    发一个数据生成器
    圆方树学习
    四校联考 推冰块
    Codeforces Training S03E01泛做
    HAOI2015 泛做
  • 原文地址:https://www.cnblogs.com/two-peanuts/p/11342492.html
Copyright © 2011-2022 走看看