目录
类视图&装饰器
基于调度方法的类视图
1.基于调度方法的类视图,可以根据不同的method来执行不同的请求。假如用户发送的get请求,则会自动执行这个类get方法。
2.将get请求相关的代码放在get方法中,与post请求相关的代码都放在post方法中,就不需要通过之前的request.method == ‘GET’ 了。可以让代码更加的简洁,方便。
这是未使用调度方法类视图的原代码:
可以看到,现在完美使用的方法需要写method=【‘post’,‘get’】以及逐个判断是否为post或者get请求。
from flask import Flask,render_template,request
app = Flask(__name__)
@app.route('/login/',methods=['GET','POST'])
def login():
if request.method == 'GET':
return render_template('login05.html')
elif request.method == 'POST':
uname = request.form.get('uname')
pwd = request.form.get('pwd')
if uname == 'xiaolin' and pwd == '123456':
return '登录成功!'
else:
return render_template('login05.html')
if __name__ == '__main__':
app.run(debug=True)
改进后:
不需要对请求类型进行判断。
from flask import Flask,render_template,request
from flask.views import MethodView
app = Flask(__name__)
class loginView(MethodView):
def get(self):
return render_template('login05.html')
def post(self):
uname = request.form.get('uname')
pwd = request.form.get('pwd')
if uname == 'xiaolin' and pwd == '123456':
return '登录成功!'
else:
return render_template('login05.html',msg='用户名或者密码错误!')
app.add_url_rule('/login/',view_func=loginView.as_view('login'))
if __name__ == '__main__':
app.run(debug=True)
基于调度方法的类视图写法优化
优化写法:
from flask import Flask,render_template,request
from flask.views import MethodView
app = Flask(__name__)
class logView(MethodView):
def _jump(self,msg = None):
return render_template('login06.html',msg = msg)
def get(self,msg = None):
return self._jump()
def post(self):
uname = request.form.get('uname')
pwd = request.form.get('pwd')
if uname == 'xiaolin' and pwd == '123456':
return '欢迎小林'
else:
return self._jump(msg = '用户名或者密码错误!请输入正确的的用户名和密码!')
app.add_url_rule('/login/',view_func=logView.as_view('login'))
if __name__ == '__main__':
app.run(debug=True)
其实主要是 render_template()这里出现了重复,可以创建一个函数单独写出去,在进行调用即可。在多次要使用重复代码的时候,可以使用,以减少代码量。
视图装饰器的使用
python装饰器:用于扩展原来函数的功能的函数,特殊之处在于它的返回值是一个函数。
优点:在不用更改原函数的代码的前提下,给函数增加新的功能。
注意:在视图函数中使用自定义装饰器,必须放在app.route()下,否则这个装饰器将不起任何作用。
例:
一个验证用户是否登录成功的装饰器 ,会将登录成功或者失败的信息传递给后台。
from flask import Flask,render_template,request
from functools import wraps
import logging
app = Flask(__name__)
# 设置日志模块
logging.basicConfig(level=logging.INFO)
def login_required(func):
@wraps(func)
def wrapper(*args,**kwargs):
uname = request.args.get('uname')
pwd = request.args.get('pwd')
if uname == 'xiaolin' and pwd == '123456':
logging.info(f'{uname}:登录成功!!')
return func(*args,**kwargs)
else:
logging.info(f'{uname}:尝试登录失败!!')
return '用户名或密码错误!'
return wrapper
@app.route('/')
@login_required
def index():
return 'hello'
if __name__ == '__main__':
app.run(debug=True)
在类视图中使用装饰器,需要重写类视图的一个类属性decorators
,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器。
@app.route('/')
@login_required
def index():
return 'hello'
class LoginViwe(MethodView):
decorators=[login_required]
def get(self):
return 'hello'
app.add_url_rule('/login/',view_func=LoginViwe.as_view('login'))
蓝图
蓝图里老是映射来映射去,烦死了有时候都搞不清楚了。
蓝图的介绍
蓝图我个人理解的话就是一个容器。
在Flask中,使用蓝图Blueprint来分模块组织管理。
那么它具有以下的特点:
- 一个应用可以具有多个Blueprint
- 可以将一个Blueprint注册到任何一个未使用的URL下比如
“/user”
、“/goods”
- Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
- 在一个应用初始化时,就应该要注册需要使用的Blueprint
注意
Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中
以一个简单的购物页面来看:
#用户模块
#登录模块
#注册模块
#退出模块
#产品模块
#获取全部产品
#获取单件产品
#更新产品
#删除产品
#批量添加产品
#收藏模块
#购物车模块
可以看到就单单几个模块就以及足够复杂了,所需要的代码量是很大的了。当产品模块需要更改的时候,时间也是很费劲的。而且若是书写不规范的模块或者耦合性高的模块间,需要修改更加费时费力。
这时候蓝图就很重要了,每一个模块都能单独创建一个蓝图来批量管理里面的子模块,不需要的时候可以直接删除该文件夹。
使用方法
1.创建一个蓝图对象(这里是用户模块):
user_pb = breakpoint('user',__name__)
2.给蓝图创建一个需要管理的蓝图地址:
@user_pb.route('/login/')
def login():
return '登录模块'
@user_pb.route('/register/')
def register():
return '注册模块'
3.需要注册这个蓝图对象:
app.register_blueprint(user_pb)
蓝图的url前缀:
可以为蓝图添加一个独特的前缀,增加辨识度。
app.register_blueprint(user_bp, url_prefix='/user')
蓝图的目录结构
在接着上一个蓝图的使用后,现在完美仍然将蓝图放在一个文件里边,造成的结果就是仍然显得很臃肿和复杂。那么为了让每个模块更加清晰,可以通过将代码分在不同的文件里进行集中管理。
可以根据功能模块和技术模块分别创建工程目录,不多赘述。
蓝图模板的使用
templates的寻找规则
如果项目中的templates文件夹中有相应的模版文件,就直接使用了。
如果项目中的templates文件夹中没有相应的模版文件,那么就到在定义蓝图的时候指定的路径中寻找。
- 并且蓝图中指定的路径可以为相对路径,相对的是当前这个蓝图文件所在的目录
在正常情况下,蓝图文件在寻找模块文件时,会以templates为根目录来进行查询。
user_bp = Blueprint('user',__name__,url_prefix='/user',template_folder='user_page')
蓝图静态文件
模板中可以有独有的静态文件
蓝图内部静态文件
蓝图对象创建时不会默认注册静态目录的路由。需要我们在创建时指定 static_folder
参数。
例:
将蓝图目录下的static_admin目录设置为静态目录
user=Blueprint("user",__name__,static_folder='user_static')
app.register_blueprint(admin,url_prefix='/user')
<body>
<h1>模板静态文件</h1>
<video src="/user/user_static/aaa.mp4" autoplay width="50%" loop="loop" muted='muted'></video>
</body>
可以通过static_url_path改变访问,这个就不做实例了。
蓝图与url_for函数的结合
跟以往不同,在蓝图中使用url_for跟默认写法不同,需要在url_for后边指定蓝图的名字。
app类中、模版中、同一个蓝图类中都是如此。否则就找不到这个endpoint
在python中:
from user import user_bp
from flask import url_for
@user_bp.route('/index/')
def index():
return '用户主页'
@user_bp.route('/')
def test_url():
return url_for('user.index')
在html中:
<video src='{{url_for("user.static",filename="aaa.mp4")}}' autoplay muted="meted" loop="loop"></video>
蓝图设置子域名
很多应用都带有子应用,比如百度里的百度地图,百度贴吧,百度新闻等等。子应用的域名基本上相等,但是前缀不同,可以利用蓝图来实现子域名。
蓝图实现子域名
1.使用蓝图技术。
2.创建蓝图对象的时候,添加一个传递一个subdomain参数,来指定子域名的前缀:
cms_bp= Blueprint('cms',__name__,subdomain='cms')
3. 需要在主app文件中,需要配置app.config的SERVER_NAME参数。
if __name__ == '__main__':
# 127.0.0.1:5000
app.config['SERVER_NAME'] = 'xiaolin.com:5000'
app.run(debug=True)
4.在windows:C:\Windows\System32\drivers\etc
下,找到hosts文件,然后添加域名与本机的映射。Linux: /etc/hosts。
域名和子域名都需要做映射。
这个很烦啊!!!!!!!
这样改(例):
127.0.0.1 xiaolin.com
127.0.0.1 python.xiaolin.com
注意
- ip地址不能有子域名
- localhost也不能有子域名
————————————————————————————————————————
Flask之视图高级---->END