• 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源码就不贴出来了,想了解可以自己导入后查看,注释写的非常明白,也都有案例
  • 相关阅读:
    CPP--关于long的争议和思考
    CPP--借助神器VS理解内存存储(含大小端对齐)
    1.QT开发第一个程序
    POJ-1456 Supermarket 贪心问题 有时间限制的最小化惩罚问题
    HDU-4310 Hero 贪心问题
    HDU-1789 Doing Homework again 贪心问题 有时间限制的最小化惩罚问题
    HDU-2303 The Embarrassed Cryptographer 高精度算法(大数取模)
    【错题本】刷算法题中出现的一些错误和小技巧
    HDU-2050 折线分割平面 找规律&递推
    记intel杯比赛中各种bug与debug【其五】:朴素贝叶斯分类器的实现和针对性的优化
  • 原文地址:https://www.cnblogs.com/jiangmingbai/p/13097932.html
Copyright © 2020-2023  润新知