20、flask---视图高级应用

1、`add_url_rule(rule,endpoint=None,view_func=None)`

       这个方法用来添加url与视图函数的映射。如果没有填写`endpoint`,那么默认会使用`view_func`的名字作为`endpoint`。以后在使用`url_for`的时候,就要看在映射的时候有没有传递`endpoint`参数,如果传递了,那么就应该使用`endpoint`指定的字符串,如果没有传递,那么就应该使用`view_func`的名字。

2、`app.route(rule,**options)`装饰器:

      这个装饰器底层,其实也是使用`add_url_rule`来实现url与视图函数映射的。


3、类视图:

3.1、标准类视图:

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

    class ListView01(views.View):
        def dispatch_request(self):
            return "list_view"
    app.add_url_rule("/list01/",view_func=ListView01.as_view('list01'))
    
    with app.test_request_context():
        print(url_for("list01"))
    class ListView01(views.View):
        def dispatch_request(self):
            return "list_view"
    
    app.add_url_rule("/list01/",endpoint='my_list',view_func=ListView01.as_view('list01'))
    
    with app.test_request_context():
        print(url_for("my_list"))

     

  • 5. 类视图有以下好处:可以继承,把一些共性的东西抽取出来放到父视图中,子视图直接拿来用就可以了。但是也不是说所有的视图都要使用类视图,这个要根据情况而定。

     我们要实现在注册页面和登陆页面都放同一个广告:

    实现方式一:

class Login(views.View):
    def dispatch_request(self):
        return render_template("login.html",adv="这是广告")

class Register(views.View):
    def dispatch_request(self):
        return render_template('Register.html',adv="这是广告")


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'))

    实现方式二:我们可以通过一个父类来将公共的部分集成起来

class ADSView(views.View):
    def __init__(self):
        super(ADSView,self).__init__()
        self.context={
            'adv':'这是广告'
        }

class Login(ADSView):
    def dispatch_request(self):
        return render_template("login.html",**self.context)

class Register(ADSView):
    def dispatch_request(self):
        return render_template('Register.html',**self.context)

如果我们需要在login类中添加新的内容,我们可以通过self.context.update()来实现

class ADSView(views.View):
    def __init__(self):
        super(ADSView,self).__init__()
        self.context={
            'adv':'这是广告'
        }

class Login(ADSView):
    def dispatch_request(self):
        self.context.update({
            'title':'登陆'
        })
        return render_template("login.html",**self.context)

class Register(ADSView):
    def dispatch_request(self):
        return render_template('Register.html',**self.context)
 

3.2、基于请求方法的类视图:

  • 1. 基于方法的类视图,是根据请求的`method`来执行不同的方法的。如果用户是发送的`get`请求,那么将会执行这个类的`get`方法。如果用户发送的是`post`请求,那么将会执行这个类的`post`方法。其他的method类似,比如`delete`、`put`。
  • 2. 这种方式,可以让代码更加简洁。所有和`get`请求相关的代码都放在`get`方法中,所有和`post`请求相关的代码都放在`post`方法中。就不需要跟之前的函数一样,通过`request.method == 'GET'`。
class LoginView(views.MethodView):
    def get(self):
        return render_template('login.html')
    def post(self):
        user=request.form.get('username')
        passw=request.form.get('password')
        if user=='bj' and passw=='123456':
            return render_template('index.html')
        else:
            return render_template('login.html',error="用户名或者密码错误")

app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆</title>
</head>
<body>
<form action="" method="post">
    <table>
        <tbody>
        <tr>
            <td>用户名</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" name="登陆"></td>
        </tr>
        </tbody>
    </table>
    {% if error %}
        <p style="color: red">{{ error }}</p>
    {% endif %}
</form>
</body>
</html>

 改进版1

class LoginView(views.MethodView):
    def get(self,error=None):
        return render_template('login.html',error=error)

    def post(self):
        user = request.form.get('username')
        passw = request.form.get('password')
        print(user, passw)
        if user == 'bj' and passw == '123456':
            return "登陆成功"
        else:
            return self.get(error="用户名或者密码错误")


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

改进版2

class LoginView(views.MethodView):
    def __render(self,error=None):
        return render_template('login.html',error=error)
    def get(self):
        return self.__render()

    def post(self):
        user = request.form.get('username')
        passw = request.form.get('password')
        print(user, passw)
        if user == 'bj' and passw == '123456':
            return "登陆成功"
        else:
            return self.__render(error="用户名或者密码错误")


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

Note:

  1. render函数前面的“__”表示的是私有方法,即__render()表示一个私有方法。

4、 类视图中的装饰器:

1. 如果使用的是函数视图,那么自己定义的装饰器必须放在`app.route`下面。否则这个装饰器就起不到任何作用。
2. 类视图的装饰器,需要重写类视图的一个类属性`decorators`,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器。

from flask import Flask, views, url_for, render_template, request
from functools import wraps
import config

app = Flask(__name__)
app.config.from_object(config)


@app.route('/')
def hello_world():
    return 'Hello World'

# 自定义一个装饰器,只有username==‘bj'才能进入个人界面
def login_required(func):
    @wraps(func)
    def wrappers(*args,**kwargs):
        username=request.args.get('username')
        if username=='bj':
            return '进入个人界面'
        else:
            return "请登陆"
    return wrappers

@app.route('/self_me/')
@login_required
def self_me():
    return '我的界面'

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

如果给自己定义的类视图添加装饰器呢?

from flask import Flask, views, url_for, render_template, request
from functools import wraps
import config

app = Flask(__name__)
app.config.from_object(config)


@app.route('/')
def hello_world():
    return 'Hello World'

# 自定义一个装饰器,只有username==‘bj'才能进入个人界面
def login_required(func):
    @wraps(func)
    def wrappers(*args,**kwargs):
        username=request.args.get('username')
        if username=='bj':
            return '进入个人界面'
        else:
            return "请登陆"
    return wrappers

@app.route('/self_me/')
@login_required
def self_me():
    return '我的界面'

# 自定义的类视图添加装饰器
class ProfileView(views.View):
    decorators = [login_required]
    def dispatch_request(self):
        return '这是个人中心界面'

app.add_url_rule('/profile/',view_func=ProfileView.as_view('profile'))

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值