zoukankan      html  css  js  c++  java
  • flask 即插视图(Pluggable Views)和endpoint

    endpoint经常使用flask的人肯定不会面生。其实我一直没有关注过他是怎么寻址的,直到最近经常食用url_for这个函数才引起了我的注意。

    url_for看源码感觉实现挺复杂的,我们姑且不在这里纠结看到这一句:

    def url_for(endpoint, **values):
        """Generates a URL to the given endpoint with the method provided.

    传入的第一个参数是endpoint,url_for函数会将挂在endpoint上面的viewfunction的url返回回来。

    当我们在正常请求flask提供的函数的时候我们使用的寻址顺序是 url -> endpoint -> viewfunction

    当我们在有viewfunction想知道url的时候 寻址顺序是 viewfunction -> endpoint -> url

    而且当有一个蓝图被申明的时候,我们使用url_for要带上蓝图的名称例如:

    ec_bp = Blueprint(
        'ec',
        __name__,
        template_folder='templates',
        static_folder='static')

    一个蓝图是这样

    那么要找到这个蓝图下面的视图函数使用url_for的时候要这样。

    url_for('ec.endpoint')

    方能够正常寻址。关于endpoint其他没有什么好说的了。

    下面来看看flask的即插视图:

     即插视图主要牵扯到两个方面的东西,首先我们要理解一个重要的概念。我们在flask中使用的装饰器路由地址与endpoint的绑定也可使用 

    add_url_rule函数进行路由绑定

        def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
            """A helper method to register a rule (and optionally a view function)
            to the application.  The endpoint is automatically prefixed with the
            blueprint's name.

    这里喔拷贝了一个 bluepoint上面的add_url_rule方法过来,其实都差不多,这里直接使用bluepoint上面的该方法可以自动进行endpoint寻址不用使用前缀所以还比较方便。绑定路由就是rule写路由, endpoint写绑定的endpoint  然后view_func写使用哪个视图函数的名字。

    这里即插视图在view_func上面一般使用类来做view_func,进行更灵活的管理。这样使用

    class RenderTemplateView(View):
        def __init__(self, template_name):
            self.template_name = template_name
        def dispatch_request(self):
            return render_template(self.template_name)
    app.add_url_rule('/about', view_func=RenderTemplateView.as_view(
        'about_page', template_name='about.html'))

    上面是官方文档上的一个例子将类RenderTemplateView使用as_view 作为视图函数 然后设置一个name 之后与/about的 url规则绑定在一起。

    即插视图继承view 实现一个自己的dispatch_request的方法。 在执行这个视图的时候会执行dispath_request这个函数里的内容,这样就可以灵活运用这个特性。

    另外 即插视图 还可以继承一个flask.view中的MethodView方法这样可以自动路由到对应的方法下面去执行函数。

    from flask.views import MethodView
    
    class UserAPI(MethodView):
        def dispatch_request(self):
            return super(UserAPI, self).dispatch_reqeust() 
        
        def get(self):
            users = User.query.all()
            ...
    
        def post(self):
            user = User.from_form_data(request.form)
            ...
    
    app.add_url_rule('/users/', view_func=UserAPI.as_view('users')

    本来没有重写dispatch_request方法会调用继承自MethodView的 dispatch_request方法路由给指定的http方法对应的函数。

    这里我们再特殊处理一下,重写父类的dispatch_reqeust方法先跑一波我们需要的逻辑,然后再调用父类的dispatch_request()方法来路由到指定的http方法上继续执行函数。而且,这里继续传递参数到父类的dispatch_reqeust方法上是没有问题的。想传还是可以传。

    可以看到这样就避免了我们写恶心的 request.method == 'post'这样恶心的判断,其实也不错。

    以上

    Reference:

    http://docs.jinkan.org/docs/flask/views.html  即插视图flask api中文文档

  • 相关阅读:
    LVS基于DR模式负载均衡的配置
    Linux源码安装mysql 5.6.12 (cmake编译)
    HOSt ip is not allowed to connect to this MySql server
    zoj 3229 Shoot the Bullet(无源汇上下界最大流)
    hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
    poj 2391 Ombrophobic Bovines(最大流+floyd+二分)
    URAL 1430 Crime and Punishment
    hdu 2048 神、上帝以及老天爷(错排)
    hdu 3367 Pseudoforest(最大生成树)
    FOJ 1683 纪念SlingShot(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/piperck/p/6060505.html
Copyright © 2011-2022 走看看