flask view 视图
flask view
1. flask view
1.1. @route
写个验证用户登录的装饰器:在调用函数前,先检查session里有没有用户
  
from functools import wraps  
from flask import session, abort  
def login_required(func):  
    @wraps(func)  
    def decorated_function(*args, **kwargs):  
        if not 'user' in session:  
            abort(401)  
        return func(*args, **kwargs)  
    return decorated_function  
app.secret_key = '12345678'  
需将此装饰器加在每个需要验证登录的请求方法上即可  
注意,必需加在route方法后  
@app.route('/admin')  
@login_required  
def admin():  
    return '<h1>Admin Dashboard</h1>'  
  
1.2. add_url_rule
  
可以直接添加路由。  
def fun_view():  
    return '<h1>view function test!</h1>'  
app.add_url_rule('/viewfun', view_func=fun_view)  
验证一下效果:  
可以查看app的路由参数:  
Map([<Rule '/viewfun' (HEAD, GET, OPTIONS) -> fun_view>,  
直接访问也可以  
http://127.0.0.1:9000/viewfun  
装饰器本质上是一个闭包函数,所以我们当然可以把它当函数使用:  
app.add_url_rule('/foo', view_func=login_required(views.foo))  
# 案例3  
    def register_api(view, endpoint, url, pk='id', pk_type='int'):  
        view_func = view.as_view(endpoint)  
        app.add_url_rule(url, defaults={pk: None},  
                         view_func=view_func, methods=['GET', ])  
        app.add_url_rule('%s<%s:%s>' % (url, pk_type, pk), view_func=view_func,  
                         methods=['POST', 'GET', 'PUT', 'DELETE'])  
    register_api(UserAPI, 'user_api', '/users/', pk='user_id')  
defaults中的参数会传给view  
  
1.3. pluggable view
之前的视图都是函数,但它也可以通过类来实现:
- 标准类视图必须继承自flask.views.View
- 必须实现dispatch_request方法,以后请求过来以后,会执行这个方法。这个方法的返回值就相当于是之前的函数视图一样,也必须返回Request或者子类的对象(字符串或者元组)。
- 必须是通过app.add_url_rule(rule,endpoint,view_func)来做url映射。
view_func这个参数,要使用as_view这个方法来转换
如果指定了endpoint,那么在使用url_for反转的时候,就要使用endpoint指定的那个值,如果没有指定那个值,就使用as_view中指定的视图名字来作为反转。
类视图有以下的好处,可以将一些共性的东西抽取出来放到父视图中,子视图直接继承就可以了,但是也不是说所有的视图都要使用类视图,这个要根据实际情况来定。
  
class Plugview1(View):  
    def dispatch_request(self, **kw):  
        text = '这里是pluggable test页面。'  
        return render_template('plug_view.html', text1=text, name=kw['name'])  
from .views import Plugview1  
view_t = Plugview1.as_view('plugview')  
app.add_url_rule('/plugview/', view_func=view_t)  
app.add_url_rule('/plugview/<name>', view_func=view_t)  
我们创建了一个”flask.views.View”的子类,并覆盖了其”dispatch_request()”函数,渲染视图的主要代码必须写在这个函数里。然后我们通过”as_view()”方法把类转换为实际的视图函数,”as_view()”必须传入一个唯一的视图名。此后,这个视图就可以由”app.add_url_rule”方法绑定到路由上了。  
效果展示:Map([<Rule '/plugview/' (HEAD, OPTIONS, GET) -> plugview>,  
  
这个例子比较简单,只是为了介绍怎么用视图类,体现不出它的灵活性,我们再看个例子:指定模板
  
class RenderTemplateView(View):  
    def __init__(self, template):  
        self.template = template  
    def dispatch_request(self):  
        return render_template(self.template)  
app.add_url_rule('/hello', view_func=RenderTemplateView.as_view('hello', template='hello-view.html'))  
app.add_url_rule('/login', view_func=RenderTemplateView.as_view('login', template='login-view.html'))  
  
1.3.1. 装饰器
视图装饰器支持
  
class HelloView(View):  
    decorators = [login_required]  
    def dispatch_request(self, name=None):  
        return render_template('hello-view.html', name=name)  
  
只需将装饰器函数加入到视图类变量”decorators”中即可。它是一个列表,所以能够支持多个装饰器,并按列表中的顺序执行。
1.3.2. 请求方法的支持
当视图要同时支持GET和POST请求时,视图类可以这么定义:
  
class MyMethodView(View):  
    methods = ['GET', 'POST']  
    def dispatch_request(self):  
        if request.method == 'GET':  
            return '<h1>Hello World!</h1>This is GET method.'  
        elif request.method == 'POST':  
            return '<h1>Hello World!</h1>This is POST method.'  
  
app.add_url_rule('/mmview', view_func=MyMethodView.as_view('mmview'))
只需将需要支持的HTTP请求方法加入到视图类变量”methods”中即可。没加的话,默认只支持GET请求。
1.3.3. 基于方法的视图
上节介绍的HTT对于RESTFul类型的应用来说,有没有更简单的方法,比如省去那些if, else判断语句呢?Flask中的”flask.views.MethodView”可以。
  
from flask.views import MethodView  
class UserAPI(MethodView):  
    def get(self, user_id):  
        if user_id is None:  
            return 'Get User called, return all users'  
        else:  
            return 'Get User called with id %s' % user_id  
    def post(self):  
        return 'Post User called'  
    def put(self, user_id):  
        return 'Put User called with id %s' % user_id  
    def delete(self, user_id):  
        return 'Delete User called with id %s' % user_id  
现在我们分别定义了get, post, put, delete方法来对应四种类型的HTTP请求,注意函数名必须这么写。怎么将它绑定到路由上呢?  
user_view = UserAPI.as_view('users')  
# 将GET /users/请求绑定到UserAPI.get()方法上,并将get()方法参数user_id默认为None  
app.add_url_rule('/users/', view_func=user_view,  
                            defaults={'user_id': None},  
                            methods=['GET',])  
# 将POST /users/请求绑定到UserAPI.post()方法上  
app.add_url_rule('/users/', view_func=user_view,  
                            methods=['POST',])  
# 将/users/<user_id>URL路径的GET,PUT,DELETE请求,  
# 绑定到UserAPI的get(), put(), delete()方法上,并将参数user_id传入。  
app.add_url_rule('/users/<user_id>', view_func=user_view,  
                                     methods=['GET', 'PUT', 'DELETE'])  
上例中”app.add_url_rule()”可以传入参数default,来设置默认值;参数methods,来指定支持的请求方法。  
如果API多,有人觉得每次都要加这么三个路由规则太麻烦,可以将其封装个函数:  
def register_api(view, endpoint, url, pk='id', pk_type='int'):  
    view_func = view.as_view(endpoint)  
    app.add_url_rule(url, defaults={pk: None},  
                     view_func=view_func, methods=['GET', ])  
    app.add_url_rule(url, view_func=view_func, methods=['POST', ])  
    app.add_url_rule('%s<%s:%s>' % (url, pk_type, pk), view_func=view_func,  
                     methods=['GET', 'PUT', 'DELETE'])  
from .views import UserAPI  
register_api(UserAPI, 'user_api', '/users/', pk='user_id')  
现在,一个”register_api()”就可以绑定一个API了  
<Rule '/users/' (OPTIONS, POST) -> user_api>,  
<Rule '/users/<user_id>' (GET, PUT, DELETE, OPTIONS, HEAD) -> user_api>,  
 <Rule '/users/' (GET, OPTIONS, HEAD) -> user_api>])  
  
    日拱一卒无有尽,功不唐捐终入海
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号