阅读(4638) (15)

Flask 即插视图基本原则

2021-06-22 15:41:26 更新

想象你有一个从数据库载入一个对象列表并渲染到视图的函数:

@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'))