1. 标准类视图及其使用
1.1 其他方法映射URL
•在此之前,我们都是通过@app.route装饰器
来实现url与视图函数的映射,除此方法外,我们也可以通过Flask对象的add_url_rule()方法
来与视图函数映射
新建视图函数文件测试:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '但行好事莫问前程'
def info():
return '不困于心'
# add_url_rule()方法映射路由
app.add_url_rule('/info/', view_func=info)
if __name__ == '__main__':
app.run(debug=True)
网页显示:
由上可得:add_url_rule()方法
可以映射路由
•add_url_rule()方法
中有一个参数endpoint,当给endpoint设置参数后url_for()方法
中传入的就不再是视图函数名了,而是指定的endpoint参数值,相当于给url取了一个名字,可供url_for()方法
调用
添加endpoint参数后测试:
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/')
def index():
return '但行好事莫问前程'
def info():
print(url_for('ycx'))
return '不困于心'
# add_url_rule()方法映射路由
app.add_url_rule('/info/', endpoint='ycx', view_func=info)
if __name__ == '__main__':
app.run(debug=True)
此时需要在url_for()中传入endpoint指定的参数(‘ycx’),访问网页成功后控制台打印/info/
1.2 标准类视图函数
•标准类视图继承自flask.views.View
,并且标准类视图中必须重写dispatch_request()方法
,这个方法类似于视图函数,会返回一个基于Response或者其子类的对象。类视图定义后,需要通过add_url_rule()方法
和路由进行映射,还需要在as_view()方法
中指定该url的名称,方便url_for()函数调用
标准类视图代码测试:
from flask import Flask, url_for, views
app = Flask(__name__)
class ListView(views.View):
def dispatch_request(self):
return '定义标准类视图'
def demo(self):
return '进行测试'
app.add_url_rule('/list/', endpoint='list', view_func=ListView.as_view('list'))
if __name__ == '__main__':
app.run(debug=True)
用url_for()方法来获取URL,需要注意:
•如果add_url_rule()
中指定了endpoint参数,url_for()
中传的参数就应该是endpoint参数的值;如果没有指定,就是as_view()方法
中的参数
在定义视图类时,必须要重写dispatch_request()方法
,否则会抛出如下异常:
查看views源码发现问题:
def dispatch_request(self):
"""Subclasses have to override this method to implement the
actual view function code. This method is called with all
the arguments from the URL rule.
"""
raise NotImplementedError()
中文翻译:
子类必须重写此方法才能实现实际的视图函数代码。使用URL规则中的所有参数调用此方法
由上可得:
•如果不重写dispatch_request()方法
,会直接抛出NotImplementedError错误
返回公共变量测试:
from flask import Flask, views, render_template
app = Flask(__name__)
@app.route('/')
def index():
return '这是首页'
class LoginView(views.View):
def dispatch_request(self):
self.context = {
'name': 'ycx'
}
return render_template('login.html', **self.context)
class RegisterView(views.View):
def dispatch_request(self):
self.context = {
'name': 'ycx'
}
return render_template('register.html', **self.context)
app.add_url_rule('/login/', view_func=LoginView.as_view('login'))
app.add_url_rule('/register/', view_func=RegisterView.as_view('register'))
if __name__ == '__main__':
app.run(debug=True)
templates目录下创建login.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h1>这是登录页面</h1>
<h2>{{ name }}</h2>
</body>
</html>
templates目录下创建register.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<h1>这是注册页面</h1>
<h2>{{ name }}</h2>
</body>
</html>
网页显示:
两个视图类中含有相同的变量,可以将相同的抽取进行优化:
代码优化:
from flask import Flask, views, render_template
app = Flask(__name__)
@app.route('/')
def index():
return '首页'
class BaseView(views.View):
def __init__(self):
super().__init__()
self.context = {
'name': 'ycx'
}
class LoginView(BaseView):
def dispatch_request(self):
return render_template('login.html', **self.context)
class RegisterView(BaseView):
def dispatch_request(self):
return render_template('register.html', **self.context)
app.add_url_rule('/login/', view_func=LoginView.as_view('login'))
app.add_url_rule('/register/', view_func=RegisterView.as_view('register'))
if __name__ == '__main__':
app.run(debug=True)
将公有变量存储到BaseView
类中,其他类视图再继承自BaseView类