Flask开发(十二)Flask视图高级技术 Flask类视图

内容纲要

本篇导读:

  • 标准类视图
  • 基于方法的类视图

之前我们接触的试图都是函数,所以一般简称为视图函数,其实视图函数也可以基于类来实现,类视图的好处就是支持继承,编写完类视图需要通过app.add_url_rule(url_rule,view_func)来进行注册。Flask类视图一般分为标准类视图和基于调度方法的类视图。

标准类视图

标准类视图的特点:

  • 必须继承flask.views.View。
  • 必须实现dispatch_request方法,以后请求过来后,都会执行这个方法,这个方法的返回值相当于之前的视图函数,也必须返回Response或子类的对象,或者是字符串、元组。
  • 必须通过app,add_url_rule(rule,endpoint,view_func)来做URL与视图的映射,view_func参数需要使用as_view类方法转换。
  • 如果指定了endpoint,那么在使用url_for反转时就必须使用endpoint指定的那个值。如果没有指定endpoint,那么就可以使用as_view(视图名称)中指定的视图名称来作为反转。

如果一个网站有首页、注册页面、和登录页面,每个页面要求防止一个同样的对联广告。使用类视图函数该如何实现?

在template文件夹中新建longin.htm、register.html、index.html文件。app.py的文件内容如下:

from flask import Flask,render_template,views
from flask.typing import ResponseReturnValue

app = Flask(__name__)
class Ads(views.View):
    def __init__(self):
        super().__init__()
        self.context = {
            'ads':'这是对联广告'
        }
class Index(Ads):
    def dispatch_request(self) -> ResponseReturnValue:
        return render_template('index.html',**self.context)

class Login(Ads):
    def dispatch_request(self) -> ResponseReturnValue:
        return render_template('longin.html',**self.context)

class Register(Ads):
    def dispatch_request(self) -> ResponseReturnValue:
        return render_template('register.html',**self.context)

app.add_url_rule('/',endpoint='index',view_func=Index.as_view('index'))
app.add_url_rule('/login',endpoint='login',view_func=Login.as_view('login'))
app.add_url_rule('/register/',endpoint='register',view_func=Register.as_view('register'))


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

在app.py中定义了一个视图函数Ads,该函数继承自flask.views.View,在该函数中,我们返回一个元祖作为Response对象。其他类视图继承自Ads,并且实现dispatch_request方法。

index.html文件的内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是首页{{ ads }}
</body>
</html>

login.html文件内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是登录页面!{{ ads }}
</body>
</html>

register.html文件内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是注册页面!{{ ads }}
</body>
</html>

运行效果如下:

基于方法的类视图

利用视图函数实现不同的请求执行不同的逻辑时比较复杂,需要在视图函数中进行判断,如果利用方法视图实现就比较简单。Flask提供了另一种类视图flask.views.MethonView,对每隔HTTP方法执行不同的函数(映射到对应的小写的同名方法上)。

新建index.html以及app.py。app.py的代码如下:

from flask import Flask,render_template,views,request
from flask.typing import ResponseReturnValue

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template('index.html')

class LoginView(views.MethodView):
    def get(self):
        return render_template('index.html')
    def post(self):
        user=request.form.get('username')
        passwd=request.form.get('pwd')
        if user == 'admin' and passwd == 'admin':
            return '用户名正确,登录成功!'
        else:
            return '用户名或密码错误,登陆失败!'

app.add_url_rule('/login',view_func=LoginView.as_view('loginview'))

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

index.html文件的内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        .div1{
            height: 180px;
            width: 380px;
            border: 1px solid #8a8989;
            margin: 0 auto;
        }
        .input{
            display: block;
            width: 350px;
            height: 40px;
            margin: 10px auto;
        }
        .button{
            background: #2066c5;
            color: white;
            font-size: 18px;
            font-weight: bold;
            height: 50px;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <div class="div1">
        <form action="login" method="post">
            <input type="text" class="input" name="username" placeholder="请输入用户名">
            <input type="password" class="input" name="pwd" placeholder="请输入密码">
            <input type="submit" value="登录" class="input button">
        </form>
    </div>
</body>
</html>

运行效果如下:

 

阅读剩余
THE END