zoukankan      html  css  js  c++  java
  • Flask-3-视图(可插拔视图)

    前沿:本次分享主要是基于类的视图

    一、什么是视图函数?

    简单来说,被url装饰的==>后面处理逻辑的方法就是视图函数,一般制作三件事,接收请求参数,数据处理逻辑、构建响应对象对并返回

    一般来说视图函数内的逻辑不应该过长,具体逻辑在另外的模块去封装,等封装的尽量尽快封装,不要等以后,以后重构的话更麻烦更累。

    二、视图函数的形式

    1、分请求方法

    路由中可以根据不同的请求方法来返回不同的东西
    比如: project 如果是get请求就返回project信息
    如果是post请求 就新增一个project

    2、分请求单复数

    路由中可以根据参数来动态决定响应对象,例如 project 接口 如果传了id,就返回对象id,的项目信息,如果没有穿则返回全部项目信息,可以定义一个默认id值,defaults = {"id":None}

    3、注意视图函数对应MVC的部分,不要越界

    视图函数应该负责哪一块已经反复强调几次,不在重复

    4、注意:

    上述说的视图形式,只是一种举例,具体怎么使用,完全靠自己习惯,你要写两个视图函数来实现,一个视图函数只做一件事情。这种也是完全OK的。遵循RESTFUL那一套也是很好,不过对于前端后不分离,我还是喜欢写一个视图中,这样处理会省事些。

    三、基于类的视图(也可以叫可插拔视图)

    1、什么是基于类的视图?

    falsk从Django那学来,以类的方式实现视图函数的逻辑,封装get,post函数,如果请求方法是get就掉用类中get函数,如果是post请求,就掉类中post的函数,根据请求方法来和类中的函数弄一个绑定关系,达到这种映射的效果,不过需要继承flask的View类。

    2、类视图有什么好处

    • 类是可以继承的
    • 代码可以复用
    • 可以定义多中行为
    • 上述说了一个视图实现多个功能的,逻辑就很多 ,此时我们用基于类的视图则比较优雅

    3、可插拔视图案例

    • 需要继承View
    • 必须重写dispatch_request方法,主要实现请求调度的作用。
    • 请求方法的限制,可以放在类的methods属性定义
    • 装饰器也可以使用自定义装饰器,用decorators属性定义
    • 类视图写完我,不能用flask的app.route装饰器来注册路由,只能用add_url_rule方法,绑定视图时用as_view()意思是将类转成视图函数用,接收一个name参数,定义视图函数的名字,或者说定义端点名。因为端点默认取的就是视图函数的名字
    • View类中都有说明,可参考VIew源码
    from flask.views import View
    from flask import Flask, request
    
    
    # 基于类的视图
    class Project(View):
        # 定义请求方法
        methods = ["GET", "POST"]
        
        # get请求方法的执行逻辑
        def get(self):
            return "get"
        
        # post请求方法执行的逻辑
        def post(self):
            return "post"
        
        # 调度函数,必须重写。不重写,View类会直接抛异常
        def dispatch_request(self):
            # 请求方法映射关系
            request_method = {"get": self.get, "post": self.post}
            # 通过requset方法获取前端访问的请求方法
            print(request.method)
            # 通过请求方法,映射到对应的函数对象
            view = request_method.get(request.method.lower())
            print(view)
            # 返回映射到的函数返回值
            return view()
    
    
    app = Flask(__name__)
    # 只能采用集中注册,用as_view方法
    app.add_url_rule("/project", view_func=Project.as_view("project"))
    
    # 可以打印看一下视图和url的绑定关系
    print(app.url_map)
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    四、来自Flask的优化MethodView类。

    上述我们自己些调度函数dispatch_request,属于硬编码,这种映射关系是我们写死的。非常不优雅。而falsk给我们另外基于View类封装一个MethodView,它里面帮我用获取类属性的方式,也就是用getattr的方法,更加优化的重写了View类的dispatch_request方法

    说这么多,所以呢?有什么用?

    只要我们的类视图继承这个MethodView类,我们就不需要在每个类视图中在重写dispatch_request。完全不需要在写这个方法了,除非你还有别的要扩展可以超继承或者重写都行

    from flask.views import View, MethodView
    from flask import Flask, request
    
    
    class Project(MethodView):
        methods = ["GET", "POST"]
    
        def get(self,project_id=None):
            if project_id is None
                return "所有项目"
            return "单个项目"
    
        def post(self):
            return "post"
        
        # 注释掉也是一样的效果,不需要在写了
        # def dispatch_request(self):
        #     request_method = {"get": self.get, "post": self.post}
        #     print(request.method)
        #     view = request_method.get(request.method.lower())
        #     print(view)
        #     return view()
    
    
    app = Flask(__name__)
    app.add_url_rule("/project/<project>", view_func=Project.as_view("project"),methods=["GET"])
    print(app.url_map)
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    五、类视图实现不同功能是的注册机制

    类视图非常适合对同一个范畴的东西,不同的功能实现,如项目操作,查询单个项目、查询所有项目、创建项目、删除项目、更新项目等等,此时我们一个类视图就都能实现了,但是在注册的时候 需要分开注册成不同的路由。

    from flask.views import View, MethodView
    from flask import Flask, request
    
    
    class Project(MethodView):
    
        def get(self, project_id=None):
            if project_id is None:
                return "所有项目"
            return "单个项目"
    
        def post(self):
            return "创建项目"
    
        def delete(self,project_id):
            return "删除项目"
    
    
    app = Flask(__name__)
    view_func = Project.as_view("project")
    # 类视图实现多个功能,我们要集中也建立多个路由,对处理
    # 获取单个项目,或删除
    app.add_url_rule("/project/<int:project_id>", view_func=view_func, methods=["GET","DELETE"])
    # 获取所有项目
    app.add_url_rule("/projects", view_func=view_func, methods=["GET"])
    # 创建项目
    app.add_url_rule("/project/create", view_func=view_func, methods=["POST"])
    print(app.url_map)
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    基于MethedVeiew,采用TESTFUL的设计思路

    URL 方法 功能说明
    /projects/ GET 获取项目列表
    /projects/ POST 创建一个项目
    /projects/ GET 获取一个项目
    /projects/ PUT 更新一个项目
    /projects/ delete 删除一个项目
    .... ..... ....

    传统的视图函数(前端后不分离的情况)

    我们通常会在函数加很多if判断

    @app.route("/projects/<project_id>", methods=["GET", "POST", "PUT", "DELETE"])
    def project(project_id):
        method = request.method
        if method == "GET":
            return f"get {project_id}"
        elif method == "post":
            return f"post {project_id}"
        # .....
        return "其他的方法判断"
    

    六、总结:

    • 基于类的视图,能够比较优雅的方式实现很多复杂的不同功能
    • 类视图定义请求方法,需要加类属性:methods = ['GET']
    • 要明白类视图其中是怎么通过请求方法,调度的,核心是基于dispatch_request方法调度的
    • 不能用@app.route()注册
    • 只能用app.add_url_rule("url",类对象.as_view(视图名字/端点名))
    • as_view 最后就是调用dispatch_request方法。
    • 类视图用装饰器时,不能在类和类方法上直接装饰,因为我们要装饰的是视图函数(也就是最后执行的是调度类函数),View类中帮我们定义了一个增加装饰器的方法,定义类属性 decorators = [装饰器函数名]
    • 说明:view和methodView源码就不贴出来了,想了解可以自己导入后查看,注释写的非常明白,也都有案例
  • 相关阅读:
    CodeForces 734F Anton and School
    CodeForces 733F Drivers Dissatisfaction
    CodeForces 733C Epidemic in Monstropolis
    ZOJ 3498 Javabeans
    ZOJ 3497 Mistwald
    ZOJ 3495 Lego Bricks
    CodeForces 732F Tourist Reform
    CodeForces 732E Sockets
    CodeForces 731E Funny Game
    CodeForces 731D 80-th Level Archeology
  • 原文地址:https://www.cnblogs.com/jiangmingbai/p/13097932.html
Copyright © 2011-2022 走看看