类视图
我们之前定义的视图都是用函数实现的,所以叫作函数视图。视图也可以使用类实现,即叫作类视图。类视图的好处是可以使用继承,把一些脚手架代码在父类中写好,子类只要聚焦到核心代码即可,从而为开发者节省时间。
基本使用
使用 Flask 类视图需要继承自 flask.views.View 类,然后在子类中实现 dispatch_request 方法,这个方法类似于视图函数,可以进行逻辑处理,并且需要返回一个响应。这里以返回所有用户列表为例,用视图函数来实现,示例代码如下。
from flask.views import View
class ShowUsers(View):
def dispatch_request(self):
users = User.query.all()
return render_template('users.html', objects=users)
app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users'))
以上代码中,首先从 flask.views 中导入 View,然后定义类视图 ShowUsers,让其继承自View。接着实现dispatch_request方法,在这个方法中,我们从数据库中获取所有的用户,并且渲染模板,其操作方式跟视图函数一样。最后再把类视图,通过app.add_url_rule方法与路由进行绑定,在绑定的时候,必须通过as_view()方法,把类转换为实际的视图函数,传给as_view方法的字符串参数是视图函数的名称,以后通过url_for进行反转时,需要使用到这个名称。此时用类视图并没有发现有什么优势,那么我们重构一下,把脚手架代码在父类中提前定义好,用子类去实现核心代码即可,示例代码如下。
from flask.views import View
class ListView(View):
def get_template_name(self):
raise NotImplementedError()
def render_template(self, context):
return render_template(self.get_template_name(), **context)
def dispatch_request(self):
context = {'objects': self.get_objects()}
return self.render_template(context)
class UserView(ListView):
def get_template_name(self):
return 'users.html'
def get_objects(self):
return User.query.all()
上述代码中,定义了一个ListView父视图,在这个父视图中提前定义好了用于获取模板的get_template_name方法,因为父视图无法知道具体的模板,所以抛出NotImplementedError异常,因此子视图必须要实现这个方法,并且返回模板路径。此外,还定义了用于渲染模板的render_template方法,以及分发请求的dispatch_request方法。子视图UserView分别实现了get_template_name和get_objects方法,这样子视图就在代码量最小的情况下实现了列表渲染功能。
方法限制
在函数视图中,通过@app.route的methods参数即可限制请求的方法。类视图则通过定义methods类属性实现限制请求的功能,示例代码如下。
class MyView(View):
methods = ['GET', 'POST']
def dispatch_request(self):
if request.method == 'POST':
# Your POST handling logic here
pass
else:
# Your GET handling logic here
pass
app.add_url_rule('/myview', view_func=MyView.as_view('myview'))
上述代码中,在MyView中定义了methods属性,以后这个类视图就只能通过GET和POST方法进行访问了。
基于方法的类视图
现在的类视图是通过判断request.method来实现不同方法的逻辑代码,如果让子视图继承自flask.views.MethodView,则可以在类视图中重写对应小写形式的方法,如GET请求则实现get方法,POST请求则实现post方法,flask会自动根据浏览器请求的HTTP方法执行对应的方法,示例代码如下。
from flask.views import MethodView
class UserAPI(MethodView):
def get(self):
users = User.query.all()
# Your logic to return the users
pass
def post(self):
user = User.from_form_data(request.form)
# Your logic to process the user data
pass
app.add_url_rule('/users/', view_func=UserAPI.as_view('users'))
以后在访问/users/这个URL时,如果用GET方法请求,那么就会执行UserAPI的get方法,用POST方法请求,就会执行UserAPI的post方法,示例代码如下。
class UserAPI(MethodView):
def get(self):
users = User.query.all()
# Your logic to return the users
pass
def post(self):
user = User.from_form_data(request.form)
# Your logic to process the user data
pass
app.add_url_rule('/users/', view_func=UserAPI.as_view('users'))