1.Flask最核心的WerkZeug和Jinja2
使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)使用Jinja2来渲染模板复制代码
2.Flask扩展包
Flask-SQLalchemy:操作数据库;Flask-migrate:管理迁移数据库;Flask-Mail:邮件;Flask-WTF:表单;Flask-script:插入脚本;Flask-Login:认证用户状态;Flask-RESTful:开发REST API的工具;Flask-Bootstrap:集成前端Twitter Bootstrap框架;Flask-Moment:本地化日期和时间;复制代码
3.Flask程序运行过程
客户端发送http请求,web服务器使用WSGI协议,把来自客户端的所有请求都交给Flask程序实例(WSGI是为 Python 语言定义的Web服务器和Web应用程序之间的一种简单而通用的接口,它封装了接受HTTP请求、解析HTTP请求、发送HTTP,响应等等的这些底层的代码和操作,使开发者可以高效的编写Web应用)程序实例使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)。根据每个URL请求,找到具体的视图函数。 在Flask程序中,路由的实现一般是通过程序实例的route装饰器实现。route装饰器内部会调用add_url_route()方法实现路由注册调用视图函数,获取响应数据后,把数据传入HTML模板文件中,模板引擎负责渲染响应数据,然后由Flask返回响应数据给浏览器,最后浏览器处理返回的结果显示给客户端。复制代码
4.状态码,重定向(redirect),render_template(),url_for,flash
a.自定义状态码,在返回的响应的后边@app.route('/')def hello_itcast(): return 'hello itcast',500b.重定向@app.route('/')def hello_itcast(): return redirect("http://www.baidu.com")c.url_for的用法1.url_for()函数是以视图函数名为参数,返回对应的url2.加载静态参数
5.错误页面的自定义以及模板上下文处理函数
a.自定义404页面(捕获异常)@app.errorhandler(404) # 传入要处理的错误代码def page_not_found(e): # 接受异常对象作为参数 user = User.query.first() return render_template('404.html', user=user), 404 # 返回模板和状态码b.模板上下文处理函数(由于多个模板都需要用到user这个变量,直接在这个函数里面取出)@app.context_processordef inject_user(): # 函数名可以随意修改 user = User.query.first() return dict(user=user) # 需要返回字典,等同于return {'user': user}复制代码
6.url的自定义
from flask import Flaskfrom werkzeug.routing import BaseConverterclass Regex_url(BaseConverter): def __init__(self,url_map,*args): super(Regex_url,self).__init__(url_map) self.regex = args[0]app = Flask(__name__)app.url_map.converters['re'] = Regex_url@app.route('/user/')def hello_itcast(id): return 'hello %s' %id复制代码
7.abort函数的使用
如果在视图函数执行过程中,出现了异常错误,我们可以使用abort函数立即终止视图函数的执行,如果abort函数被触发,其后面的语句将不会执行from flask import Flask,abort@app.route('/')def hello_itcast(): abort(404) return 'hello itcast',999注意abort里面的状态码必须就是HTTP状态码,不能自己随便写。常见状态码如下:状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:1xx:指示信息--表示请求已接收,继续处理2xx:成功--表示请求已被成功接收、理解、接受3xx:重定向--要完成请求必须进行更进一步的操作4xx:客户端错误--请求有语法错误或请求无法实现5xx:服务器端错误--服务器未能实现合法的请求常见状态码:复制代码
8.请求钩子
Flask的请求钩子指的是在执行视图函数前后执行的一些函数,我们可以在这些函数里面做一些操作。Flask利用装饰器给我们提供了四种钩子函数。
before_first_request:在处理第一个请求前执行。比如链接数据库操作 before_request:在每次请求前执行。比如权限校验 after_request:每次请求之后调用,前提是没有未处理的异常抛出 teardown_request:每次请求之后调用,即使有未处理的异常抛出
from flask import Flaskapp = Flask(__name__)@app.route('/')def index(): print('视图函数执行') return 'index page'# 在第一次请求之前运行.@app.before_first_requestdef before_first_request(): print('before_first_request')# 在每一次请求前都会执行@app.before_requestdef before_request(): print('before_request')# 在请求之后运行@app.after_requestdef after_request(response): # response: 就是前面的请求处理完毕之后, 返回的响应数据,前提是视图函数没有出现异常 # 如果需要对响应做额外处理,可以再这里进行 # json.dumps 配置请求钩子 # response.headers["Content-Type"] = "application/json" print('after_request') return response# 无论视图函数是否出现异常,每一次请求之后都会调用,会接受一个参数,参数是服务器出现的错误信息@app.teardown_requestdef teardown_request(error): print('teardown_request: error %s' % error)if __name__ == '__main__': app.run(debug=True)复制代码
9.request对象常用属性
10.文件上传
上传文件也是我们经常用到的功能,前端上传一张文件,然后后端处理保存到服务器上。 文件这种类型属于多媒体类型资源。前端form表单里面需要加enctype="multipart/form-data"。我们新建一个名upload.html模板 模板里面写如下代码:
复制代码
upload.py文件代码如下:(同级目录下创建media文件夹)
from flask import Flask, request,render_template,redirect,url_forfrom werkzeug.utils import secure_filenameimport osfrom flask import send_from_directoryapp = Flask(__name__)UPLOAD_FOLDER = 'media'ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER# 判断上传的文件是否是允许的后缀def allowed_file(filename): return "." in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS@app.route('/upload',methods=['GET','POST'])def upload(): '''文件上传''' if request.method == 'GET': return render_template('upload.html') else: print(request.files) print(type(request.files)) if "file" not in request.files: return redirect(request.url) file = request.files.get('file') # 获取文件 print(type(file)) if file.filename == '': return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) # 用这个函数确定文件名称是否是安全 (注意:中文不能识别) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) # 保存文件 return redirect(url_for('show',filename=filename))# 展示图片@app.route('/show/')def show(filename): # send_from_directory可以从目录加载文件 return send_from_directory(app.config['UPLOAD_FOLDER'], filename)复制代码
11.Flask框架上下文
参考:https://juejin.im/post/5ccd3670f265da0373719711复制代码
12.Response
视图在接收HttpRequest并处理后,必须返回HttpResponse对象, 可以使用make_response()函数然后再进行修改 示例代码:
from flask import Flask, render_template, make_responseapp = Flask(__name__)@app.route('/setcookie', methods=['GET', 'POST']) # 支持get、post请求def setcookie(): # 视图函数 resp = make_response(render_template('cookie.html')) # 显式转换成HttpResponse对象 return respapp.config['DEBUG'] = Trueif __name__ == '__main__': # 0.0.0.0代表任何能代表这台机器的地址都可以访问 app.run(host='0.0.0.0', port=5000) # 运行程序复制代码
13.自定义响应信息
自定义响应信息,可以用make_response函数。make_response(),相当于Django中的HttpResponse,效果是一样的。
from flask import Flask, abort, Response, make_responseapp = Flask(__name__)@app.route('/')def index(): # return ('自定义响应信息', 502, {"name": "xiaosong", "age": 12}) # 可以不加括号,会自动组装成元组 # return '自定义响应信息', 502, {"name": "xiaosong", "age": 12} # 自定义状态码 可以加上描述信息 # return '自定义响应信息', '520 love error', {"name": "xiaosong", "age": 12} resp = make_response() resp.headers['name'] = 'xiaosong' resp.status = '520 love error' return respif __name__ == '__main__': # 0.0.0.0代表任何能代表这台机器的地址都可以访问 app.run(host='0.0.0.0', port=5000, debug=True) # 运行程序复制代码
使用jsonfy返回响应信息和直接json.dumps(data)返回信息是不同的,表现在响应头中的Content-Type字段
jsonify:
Content-Type: application/json
json.dumps(data):
Content-Type: text/html; charset=utf-8