Flask 即插视图基本原则
想象你有一个从数据库载入一个对象列表并渲染到视图的函数:
@app.route('/users/')
def show_users(page):
users = User.query.all()
return render_template('users.html', users=users)
这是简单而灵活的,但如果你想要用一种通用的,同样可以适应其它模型和模板的 方式来提供这个视图,你会需要更大的灵活性。这就是基于类的即插视图所做的。 第一步,把它转换为基于类的视图,你要这样做:
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/', ShowUsers.as_view('show_users'))
如你所见,你需要做的是创建一个 flask.views.View 的子类, 并且实现 dispatch_request() 。然后我们需要用类方法 as_view() 把这个类转换到一个实际的视图函数。你传给 这个函数的字符串是视图之后的最终名称。但是用它自己实现的方法不够有效,所以 我们稍微重构一下代码:
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()
这当然不是那么有助于一个小例子,但是对于解释基本原则已经很有用了。当你有一 个基于类的视图,那么问题来了, self 指向什么。它工作的方式是,无论何时请 求被调度,会创建这个类的一个新实例,并且 dispatch_request() 方法会以 URL 规则为参数调用。 这个类本身会用传递到 as_view() 函数的参数来实例化。 比如,你可以像这样写一个类:
class RenderTemplateView(View):
def __init__(self, template_name):
self.template_name = template_name
def dispatch_request(self):
return render_template(self.template_name)
然后你可以这样注册它:: And then you can register it like this:
app.add_url_rule('/about', view_func=RenderTemplateView.as_view(
'about_page', template_name='about.html'))