Flask 学习笔记
一、视图函数
之前我们接触的视图都是函数,所以一般简称 “视图函数”。视图函数除了可以通过 @app.route("")
装饰器进行 url 映射外,还可以通过 app.add_url_rule(url_rule, view_func)
进行映射。
def login():
# 如果 add_url_rule 设了参数 endpoint, 相当于给 URL 起了一个别名
# 可以通过别名, 反转获取 url(endpoint 优先级比 view_func 高)
# print(url_for("lg"))
print(url_for("login"))
return "不使用 @app.route("") 装饰器进行渲染"
# app.add_url_rule('/login/', endpoint='lg', view_func=login)
app.add_url_rule('/login/', view_func=login)
二、类视图
2.1、标准类视图
其实视图也可以基于类来实现,类视图的好处是支持继承。标准类视图是继承自 flask.views.View
,并且在子类中必须重写 dispatch_request
方法,因为它会主动抛出异常(详情看源码)。这个方法类似于视图函数,也要通过 app.add_url_rule(url_rule,view_func)
来进行注册,返回一个基于 Response 或者其子类的对象。
from flask import views
# from flask.views import View
class ListView(views.View):
def dispatch_request(self):
return "类视图"
# 类视图通过 add_url_rule 方法和 url 做映射
# 并且在 as_view 方法中指定该 url 的名称, 方便 url_for 函数调用
app.add_url_rule('/list/', view_func=ListView.as_view("lv"))
2.2、基于调度方法的视图
Flask 还为我们提供了另外一种类视图 flask.views.MethodView
,对每个 HTTP 方法执行不同的函数(映射到对应方法的小写的同名方法上)。这里介绍一款可以模拟浏览器各种请求的软件 Postman
class LoginView(views.MethodView):
def get(self):
return render_template("login.html")
def post(self):
name = request.form.get("name")
pwd = request.form.get("pwd")
if (name == "xxx" and pwd == "123"):
return "登录成功!"
else:
# 当登录失败时, 再次跳转到登录页面 并提示错误
return render_template("login.html", error="账号密码错误")
app.add_url_rule('/lg/', view_func=LoginView.as_view("lg"))
因为 get 与 post 的返回基本相同,所有还可以稍微优化一下代码
class LoginView(views.MethodView):
def get(self, error):
return render_template("login.html", error=error)
def post(self):
name = request.form.get("name")
pwd = request.form.get("pwd")
if (name == "xxx" and pwd == "123"):
return "登录成功!"
else:
return self.get("账号密码错误")
app.add_url_rule('/lg/', view_func=LoginView.as_view("lg"))
当然还可以把 render_template 单独拿出来封装成函数,根据需要传参数。
def rend_temp(self, *args, **kwargs):
return render_template("login.html")
2.3、在类视图中使用装饰器
用类视图的一个缺陷就是比较难用装饰器来装饰,要在类视图中定义一个属性叫做 decorators
的列表变量,然后存储装饰器。如登录之后才能访问
# 登录之后才能访问的装饰器
def login_required(func):
def wrapper(*args, **kwargs):
# 获取 ? 类型 url(get 提交)
username = request.args.get("username")
if username:
return func(*args, **kwargs)
else:
return "请先登录"
return wrapper
class ProfileView(views.View):
# 在类中用装饰器
decorators = [login_required]
def dispatch_request(self):
return "个人页面"
app.add_url_rule('/pv/', view_func=ProfileView.as_view("pv"))