Flask框架——(视图高级)
1. 类视图
介绍:
类视图的好处是⽀持继承,但是类视图不能跟函数视图⼀样,写完
类视图还需要通过app.add_url_rule(url_rule,view_func)来进⾏注册。
1-1. 标准类视图
介绍:
标准类视图是继承⾃flask.views.View,并且在⼦类中必须实现dispatch_request⽅法,这个⽅法类似于视图函数,也要返回⼀个基于Response或者其⼦类的对象。
代码示例:
from flask.views import View
class PersonalView(View):
def dispatch_request(self):
return "测试页"
# 类视图通过add_url_rule⽅法和url做映射
app.add_url_rule('/users/',view_func=PersonalView.as_view('personalvi
ew'))
1-2. 基于调度方法的视图
介绍:
Flask还为我们提供了另外⼀种类视图flask.views.MethodView,对每个HTTP⽅法执⾏不同的函数(映射到对应⽅法的⼩写的同名⽅法上)。
代码示例:
class LoginView(views.MethodView):
# 当客户端通过get⽅法进⾏访问的时候执⾏的函数
def get(self):
return render_template("login.html")
# 当客户端通过post⽅法进⾏访问的时候执⾏的函数
def post(self):
email = request.form.get("email")
password = request.form.get("password")
if email == 'xx@qq.com' and password == '111111':
return "登录成功!"
else:
return "⽤户名或密码错误!"
# 通过add_url_rule添加类视图和url的映射,并且在as_view⽅法中指定该url的名称,⽅便url_for函数调⽤
app.add_url_rule('/myuser/',view_func=LoginView.as_view('loginview')
)
⽤类视图的⼀个缺陷就是⽐较难⽤装饰器来装饰,⽐如有时候需要做权限验证的时候
代码示例:
from flask import session
def login_required(func):
def wrapper(*args,**kwargs):
if not session.get("user_id"):
return 'auth failure'
return func(*args,**kwargs)
return wrapper
装饰器写完后,可以在类视图中定义⼀个属性叫做decorators,然后存储装饰器。以后每次调⽤这个类视图的时候,就会执⾏这个装饰器。
代码示例:
class UserView(views.MethodView):
decorators = [user_required]
...
2. 蓝图和子域名
2-1. 蓝图
介绍:
之前我们写的url和视图函数都是处在同⼀个⽂件,如果项⽬⽐较⼤的话,这显然不是⼀个合理的结构,⽽蓝图可以优雅的帮我们实现这种需求。
代码示例:
from flask import Blueprint
bp = Blueprint('user',__name__,url_prefix='/user/')
@bp.route('/')
def index():
return "⽤户⾸⻚"
@bp.route('profile/')
def profile():
return "个⼈简介"
然后我们在主程序中,通过app.register_blueprint()
⽅法将这个蓝图注册进url映射中,看下主app的实现。
代码示例:
from flask import Flask
import user
app = Flask(__name__)
app.register_blueprint(user.bp)
if __name__ == '__main__':
app.run(host='0.0.0.0',port=9000)
以后访问/user/,/user/profile/,都是执⾏的user.py⽂件中的视图
函数,这样就实现了项⽬的模块化。
以上是对蓝图的⼀个简单介绍,但是使⽤蓝图还有⼏个需要注意的地⽅,就是在蓝图如何寻找静态⽂件、模板⽂件,url_for函数如何反转url。
2-1-1. 寻找静态文件
介绍:
默认不设置任何静态文件路径,Jinja2会在项目的static文件夹中寻找静态文件。也可以设置其他的路径,在初始化蓝图的时候,Blueprint这个构造函数,有一个参数static_folder可以指定静态文件的路径
代码示例:
bp = Blueprint('admin',__name__,url_prefix='/admin',template_folder='templates')
模板文件和静态文件有点区别,以上代码写完以后,如果你渲染一个模板return render_template('admin.html')
,Flask默认会去项目根目录下的templates文件夹中查找admin.html文件,如果找到了就直接返回,如果没有找到,才会去蓝图文件所在的目录下的templates文件夹中寻找。
2-1-2. url_for
生成url
介绍:
用url_for生成蓝图的url,使用的格式是:蓝图名称+.+视图函数名称
。比如要获取admin这个蓝图下的index视图函数的url
代码示例:
url_for('admin.index')
其中这个蓝图名称是在创建蓝图的时候,传入的第一个参数
bp = Blueprint('admin',__name__,url_prefix='/admin',template_folder='templates')
2-2. 子域名
介绍:
子域名在许多网站中都用到了,比如一个网站叫做xxx.com,那么我们可以定义一个子域名cms.xxx.com来作为cms管理系统的网址,子域名的实现一般也是通过蓝图来实现,在之前章节中,我们创建蓝图的时候添加了一个url_prefix=/user作为url前缀,那样我们就可以通过/user/来访问user下的url。但使用子域名则不需要。另外,还需要配置SERVER_NAME,
比如app.config[SERVER_NAME]='example.com:9000'
。并且在注册蓝图的时候,还需要添加一个subdomain的参数,这个参数就是子域名的名称 。
代码示例:
from flask import Blueprint
bp = Blueprint('admin',__name__,subdomain='admin')
@bp.route('/')
def admin():
return 'Admin Page'
这个没有多大区别,接下来看主app的实现
代码示例:
from flask import Flask
import admin
# 配置`SERVER_NAME`
app.config['SERVER_NAME'] = 'example.com:8000'
# 注册蓝图,指定了subdomain
app.register_blueprint(admin.bp)
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8000,debug=True)
tips:
写完以上两个文件后,还是不能正常的访问admin.example.com:8000这个子域名,因为我们没有在host文件中添加域名解析,你可以在最后添加一行127.0.0.1 admin.example.com,就可以访问到了。另外,子域名不能在127.0.0.1上出现,也不能在localhost上出现。