视图
FBV
def index(nid): """ 请求相关信息 request.method # 请求方式 request.args # get 方式的参数获取 request.form # post 方式的参数获取 request.values request.cookies request.headers request.path # 请求资源路径 request.full_path # 请求全部资源漫画 request.script_root request.url # 全部请求路径 (带协议带域名) request.files # 请求文件 obj = request.files['the_file_name'] obj.save('/var/www/uploads/' + secure_filename(f.filename)) """ dic = { "k1":"v1"} """ 返回响应体的4种形式 字符串 jsonify 模板 跳转 url """ # return "index" # return jsonify(dic) # return render_template("xxx.html",dic=dic) # 可带数据传递 # return redirect(url_for("index")) # 跳转通过 url_for 反向解析 """ 定制响应头的时候构造响应体用到 make_response """
# 如果想设置响应头和回显cookie,就需要用到make_response # response = make_response(render_template('index.html')) # response = make_response("字符串") # response是flask.wrappers.Response类型 # response.delete_cookie('key') # response.set_cookie('key', 'value') # response.headers['X-Something'] = 'A value' # return response
from flask import make_response,headers,set_cookie obj = make_response(jsonify(dic)) obj.headers["xxxxx"] = "123" obj.set_cookie("key","value") return obj
装饰器实现中间件功能
预备处理视图函数初始状态
@app.route('/index')def index(): if not session.get('user'): return redirect(url_for('login')) return render_template('index.html',stu_dic=STUDENT_DICT)
视图级别加装,比较适用于对少量视图进行处理
import functoolsdef auth(func): @functools.wraps(func) def inner(*args,**kwargs): if not session.get('user'): return redirect(url_for('login')) ret = func(*args,**kwargs) return ret return inner@app.route('/index')@authdef index(): return render_template('index.html',stu_dic=STUDENT_DICT)
全局级别加装
@app.before_requestdef xxxxxx(): if request.path == '/login': return None if session.get('user'): return None return redirect('/login')
除了 before_request 以外还有其他特殊装饰器:
1. before_request 谁先定义谁先执行 执行多个 before 的时候如果再中间有返回值,对于after 的执行直接执行最后一次定义的那个 2. after_request 谁后定义谁执行 3. before_first_request4. template_global5. template_filter6. errorhandler
from flask import Flaskapp = Flask(__name__)@app.before_requestdef x1(): print('before:x1') return '滚'@app.before_requestdef xx1(): print('before:xx1')@app.after_requestdef x2(response): print('after:x2') return response@app.after_requestdef xx2(response): print('after:xx2') return response@app.route('/index')def index(): print('index') return "Index"@app.route('/order')def order(): print('order') return "order"if __name__ == '__main__': app.run()
from flask import Flaskapp = Flask(__name__)@app.before_first_requestdef x1(): print('123123')@app.route('/index')def index(): print('index') return "Index"@app.route('/order')def order(): print('order') return "order"if __name__ == '__main__': app.run()
@app.errorhandler(404)def not_found(arg): print(arg) return "没找到"
CBV
def auth(func): def inner(*args, **kwargs): result = func(*args, **kwargs) return result return inner# 继承自views.MethodView 采用CBV写法时,为了简单,都是采用继承MethodView的方式写的class IndexView(views.MethodView): # methods = ['POST'] #只允许POST请求访问 decorators = [auth,] #如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定 def get(self): #如果是get请求需要执行的代码 v = url_for('index') print(v) return "GET" def post(self): #如果是post请求执行的代码 return "POST"app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) #name指定的是别名,会当做endpoint使用
def auth(func): def inner(*args, **kwargs): print('before') result = func(*args, **kwargs) print('after') return result return inner# 也可以再往上继承自Viewclass IndexView(views.View): methods = ['GET'] decorators = [auth, ] # 如果继承自View,就需要dispatch_request def dispatch_request(self): print('Index') return 'Index!'app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) # name=endpoint
文件上传
客户端
- 必须要在表单中上传
- 提交方式必须是 post
- enctype 属性必须是 multipart/form-data
服务端
文件会上传到缓存区, 通过 request.files 获取上传文件
拿到返回值可以调用 save , filename 方法
f = request.file['name'] # f.save('路径') # f.filename # 得到文件原始名称 f.save('static/' + f.filename) # 如果不存在 static 会报错
此方法在上传重名文件的时候会覆盖, 因此需要自己设定绝不会重名的方式,比如用时间戳
中间件
首先要知道我们利用请求扩展里提供的装饰器也能够做一些中间件的事,我们这里说的是根据flask的源码流程进行自定义方法来实现中间件的操作
具体流程:
app.run会执行werkzeug(第三方WSGI模块)中的run_simple方法,继而执行inner方法,继续执行make_server方法,
make_sever方法就会返回一个BaseWSGIServer对象,主要是起socket,
当有请求过来时就会触发flask的call方法,继而执行wsgi_app方法
利用app.run中的wsgi_app方法可以自定义类,定义的_ _call_ _方法里就可以做一些中间件的事
from flask import Flaskapp = Flask(__name__)@app.route('/')def index(): return 'Hello World!'class Md(object): def __init__(self,old_wsgi_app): self.old_wsgi_app = old_wsgi_app def __call__(self, environ, start_response): print('开始之前') ret = self.old_wsgi_app(environ, start_response) print('结束之后') return retif __name__ == '__main__': app.wsgi_app = Md(app.wsgi_app) app.run()