1 路由html
1.1app.url_map 查看全部路由前端
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): """定义视图函数""" print(app.url_map) return "hello flask" @app.route('/index') def index(): return 'index' if __name__ == '__main__': app.run(debug=True)
访问127.0.0.1 :5000python
显示当前全部的路由,和每条路由的访问方式。正则表达式
1.2经过method限定访问方式数据库
给index函数添加methodjson
@app.route('/index', methods=["post"]) def index(): return 'index'
此时去浏览器在地址栏输入地址访问,flask
很显然,不让get请求,给method列表中添加get请求方式。浏览器
@app.route('/index', methods=["post", 'get']) def index(): return 'index'
此时就能get和post请求服务器
1.3同一路由装饰多个视图函数cookie
添加两个视图函数
@app.route('/test') def test1(): return "test1" @app.route("/test") def test2(): return "test2"
在浏览器访问127.0.0.1:5000/test,返回的是test1.
修改两个函数的请求方式
@app.route('/test', methods=["post"]) def test1(): return "test1" @app.route("/test", methods=["get"]) def test2(): return "test2"
再去浏览器访问127.0.0.1:5000/test,返回的是test2
1.4同一视图多个路由装饰器
添加一个func视图函数
@app.route("/func1") @app.route("/func2") def func(): return "func"
在浏览器访问127.0.0.1:5000/func1和 127.0.0.1:5000/func2,返回的结果都是func。
1.5 使用url_for进行反解析
添加一个login视图函数
from flask import Flask, redirect, url_for @app.route("/login") def login(): url = url_for("index") # 使用url_for,经过视图函数的名字找到视图对应url return redirect(url)
访问127.0.0.1:5000/login,而后就会直接跳转到index页面。
1.6 动态路由
# 路由传递的参数默认当作string处理,这里指定int,尖括号中冒号后面的内容是动态的 @app.route('/book/<int:book_id>') def book_detail(book_id): return "book detail %s" % book_id
# 路由传递的参数默认当作string处理,这里指定int,尖括号中冒号后面的内容是动态的 # @app.route('/book/<int:book_id>') @app.route('/book/<book_id>') # 不加转换器类型,默认时普通字符串规则,除了 / 字符 def book_detail(book_id): return "book detail %s" % book_id
1.7 自定义转换器
from werkzeug.routing import BaseConverter # 1.定义本身的转换器 class RegexConverter(BaseConverter): def __init__(self, url_map, regex): # 调用父类的初始化方法 super().__init__(url_map) # 将正则表达式的参数保存到对象的属性中, flask会去使用这个属性来进行路由的正则匹配 self.regex = regex # 2.将自定义的转换器添加到flask的应用中 app.url_map.converters["re"] = RegexConverter # 127.0.0.1:5000/send/178456123789 @app.route("/send/<re(r'1[34578]\d{9}'):mobile>") def send_msg(mobile): return "send_msg---To:%s" % mobile
1.8 转换器转换过程
自定义的转换器RegexConverter添加两个方法,他们都是父类BaseConverter的方法,如今看下他们实际上是在作什么。
to_python
# 1.定义本身的转换器 class RegexConverter(BaseConverter): def __init__(self, url_map, regex): # 调用父类的初始化方法 super().__init__(url_map) # 将正则表达式的参数保存到对象的属性中, flask会去使用这个属性来进行路由的正则匹配 self.regex = regex def to_python(self, value): print(value) return 123 def to_url(self, value): pass # 2.将自定义的转换器添加到flask的应用中 app.url_map.converters["re"] = RegexConverter # 127.0.0.1:5000/send/178456123789 @app.route("/send/<re(r'1[34578]\d{9}'):mobile>") def send_msg(mobile): return "send_msg---To:%s" % mobile
在浏览器访问http://127.0.0.1:5000/send/17845678912,页面显示
控制台属输出17845678912。转换过程:
to_url
class RegexConverter(BaseConverter): def __init__(self, url_map, regex): # 调用父类的初始化方法 super().__init__(url_map) # 将正则表达式的参数保存到对象的属性中, flask会去使用这个属性来进行路由的正则匹配 self.regex = regex def to_python(self, value): # print(value) # value是在路径进行正则表达式匹配的时候提取的参数 # return 123 return value def to_url(self, value): print(value) return "15612187594" # 2.将自定义的转换器添加到flask的应用中 app.url_map.converters["re"] = RegexConverter # 127.0.0.1:5000/send/178456123789 @app.route("/send/<re(r'1[34578]\d{9}'):mobile>") def send_msg(mobile): return "send_msg---To:%s" % mobile @app.route("/index") def index(): url = url_for("send_msg", mobile="18732141231") return redirect(url)
访问http://127.0.0.1:5000/index, 页面显示:
控制台输出:18732141231, 转换过程:
to_url是在使用url_for方法的时候被调用。
2 获取请求参数
from flask import request
就是 Flask 中表示当前请求的 request 对象,request对象中保存了一次HTTP请求的一切信息。
from flask import Flask, request app = Flask(__name__) @app.route("/index", methods=["get", 'post']) def index(): # request中包含了前端发送过来的全部请求数据 # form和data是用来提取请求体数据 # 经过request.form能够直接提取请求体中的表单格式的数据, 是一个类字典的对象 # 经过get方法只能拿到多个同名参数的第一个 name = request.form.get("name") age = request.form.get("age") # getlist能够获取同名的全部数据 name_list = request.form.getlist("name") print("request.data", request.data) # 发送json数据 # 127.0.0.1:5000/index?page=1 查询字符串 QueryString # args使用提取url中的参数(查询字符串) page = request.args.get("page") print(page) return "%s:%s,,%s" % (name, age, name_list) if __name__ == '__main__': app.run()
2.1 上传文件
已上传的文件存储在内存或是文件系统中一个临时的位置。你能够经过请求对象的 files 属性访问它们。每一个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save() 方法,这个方法容许你把文件保存到服务器的文件系统上。这里是一个用它保存文件的例子:
@app.route("/upload", methods=['post']) def upload(): # 接收前端发送过来的文件 file_obj = request.files.get("pic") # if file_obj is None: # return "未上传文件" # # 将文件保存到本地 # # 1.建立一个文件对象 # f = open('./test.png', 'wb') # # 2.向文件写内容 # content = file_obj.read() # f.write(content) # # 3.关闭文件 # f.close() # 直接使用上传文件的对象保存 file_obj.save("./test1.png") return "上传成功"
3 abort函数与自定义异常处理
3.1 abort函数
from flask import abort
@app.route("/login", methods=['get']) def login(): name = "hhh" pwd = '123' if name != "aaa" or pwd != 123: # 使用abort函数能够当即终止视图函数的执行, 并能够返回了浏览器特定的信息 # 1.传递状态码信息, 必须是标准的http状态码 abort(404) # 2.传递响应体信息 # res = Response("login failed") # abort(res) return "login success"
3.2 自定义异常处理
@app.errorhandler(404) def handle_error(err): """自定义处理错误方法""" # 这个函数的返回值会是用户看到的最终结果 return "首页已换, 下次记得收藏网站。。%s" % err
4 返回的响应数据
4.1 元组
能够返回一个元组,这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 能够是一个列表或字典,做为额外的消息标头值。
@app.route("/index") def index(): # 使用元祖返回自定义的响应信息 # 响应头 状态码 响应头 # return "使用元祖返回自定义的响应信息", 400, [("name", "haha")] # return "使用元祖返回自定义的响应信息", 400, {("name", "haha")} # return "使用元祖返回自定义的响应信息", 666, {("name", "haha")} # return "使用元祖返回自定义的响应信息", "666 mystatus", {("name", "haha")} # return "使用元祖返回自定义的响应信息", "666 mystatus"
4.2 make_response
from flask import make_response @app.route("/index") def index(): # 使用make_response来构造响应信息 res = make_response("使用make_response来构造响应信息") res.status = "666 mystatus" # 设置状态码 res.headers["name"] = "haha" # 设置响应头 return res
5 使用jsonify返回json数据
from flask import jsonify @app.route("/index") def index(): data = {"title": "santi", "price": 90} # return json.dumps(data) # 此时响应头的Content-Type: text/html; charset=utf-8 # 手动设置Content-Type # return json.dumps(data), 200, {"Content-Type": "application/json"} # 使用jsonify, jsonify帮助转换json数据, 并设置响应头Content-Type": "application/json" # return jsonify(data) return jsonify(title="santi", price=90)
6 设置和读取cookie
from flask import Flask, make_response, request app = Flask(__name__) @app.route("/set_cookie") def set_cookie(): res = make_response("set_cookie") # 默认有效期是临时cookie, 浏览器关闭就失效 # res.set_cookie("name", "test") # max_age设置有效期, 单位:秒 # res.set_cookie("name1", "test1", max_age=3600) # 经过响应头设置cookie # res.headers["Set-Cookie"] = "name2=test2; Expires=Sun, 28-Apr-2019 12:37:29 GMT; Max-Age=3600; Path=/" return res @app.route("/get_cookie") def get_cookie(): cook = request.cookies.get("name1") return cook @app.route("/delete_cookie") def delete_cookie(): res = make_response("delete_cookie") res.delete_cookie("name1") return res if __name__ == '__main__': app.run()
7 session
from flask import session 须要设置secret_key
from flask import Flask, session app = Flask(__name__) app.config["SECRET_KEY"] = "qlxmxlnmj" @app.route("/login") def login(): # 设置session session["name"] = "test" return "login success" @app.route("/index") def index(): # 获取session name= session.get("name") return "session :: %s" %name if __name__ == '__main__': app.run()
8 请求上下文与应用上下文
上下文:至关于一个容器,保存了Flask程序运行过程当中的一些信息。
Flask中有两种上下文,请求上下文和应用上下文。
8.1 请求上下文(request context)
request和session都属于请求上下文对象。
request:封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。
session:用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,能够记录用户信息。还能够经过session.get('name')获取用户信息。
8.2 应用上下文(application context)
current_app和g都属于应用上下文对象。
current_app:表示当前运行程序文件的程序实例。咱们能够经过current_app.name打印出当前应用程序实例的名字。
g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量。好比:咱们能够获取一些临时请求的用户信息。
当调用app = Flask(_name_)的时候,建立了程序应用对象app;
request 在每次http请求发生时,WSGI server调用Flask.call();而后在Flask内部建立的request对象;
app的生命周期大于request和g,一个app存活期间,可能发生屡次http请求,因此就会有多个request和g。
最终传入视图函数,经过return、redirect或render_template生成response对象,返回给客户端。
区别: 请求上下文:保存了客户端和服务器交互的数据。 应用上下文:在flask程序运行过程当中,保存的一些配置信息,好比程序文件名、数据库的链接、用户信息等。
9 请求钩子
在客户端和服务器交互的过程当中,有些准备工做或扫尾工做须要处理,好比:在请求开始时,创建数据库链接;在请求结束时,指定数据的交互格式。为了让每一个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
请求钩子是经过装饰器的形式实现,Flask支持以下四种请求钩子:
before_first_request:在处理第一个请求前运行。
before_request:在每次请求前运行。
after_request:若是没有未处理的异常抛出,在每次请求后运行。
teardown_request:在每次请求后运行,即便有未处理的异常抛出。
from flask import Flask app = Flask(__name__) @app.route("/index") def index(): print("index 被执行") return "index" @app.before_first_request def handle_before_first_request(): """在第一次请求处理以前被执行""" print("handle_before_first_request 被执行") @app.before_request def handle_before_request(): """在每次请求以前都被执行""" print("handle_before_request 被执行") @app.after_request def handle_after_request(response): """在每次请求(视图函数处理)以后都被执行, 前提是视图函数没有出现异常""" print("handle_after_request 被执行") return response @app.teardown_request def handle_teardown_request(response): """在每次请求(视图函数处理)以后都被执行, 不管视图函数是否出现异常,都被执行""" print("handle_teardown_request 被执行") return response if __name__ == '__main__': app.run()
启动服务器,在浏览器访问index,控制台输出结果:
服务器不重启,再次刷新浏览器,控制台输出:
在index函数中添加一个异常,
from flask import Flask app = Flask(__name__) @app.route("/index") def index(): print("index 被执行") int("A") return "index" @app.before_first_request def handle_before_first_request(): """在第一次请求处理以前被执行""" print("handle_before_first_request 被执行") @app.before_request def handle_before_request(): """在每次请求以前都被执行""" print("handle_before_request 被执行") @app.after_request def handle_after_request(response): """在每次请求(视图函数处理)以后都被执行, 前提是视图函数没有出现异常""" print("handle_after_request 被执行") return response @app.teardown_request def handle_teardown_request(response): """在每次请求(视图函数处理)以后都被执行, 不管视图函数是否出现异常,都被执行, 工做在非调试模式, debug=false""" print("handle_teardown_request 被执行") return response if __name__ == '__main__': app.run()
把调试模式关了, 重启服务器,在浏览器访问,控制台输出:
10 Flask-Script扩展命令行
经过使用Flask-Script扩展,咱们能够在Flask服务器启动的时候,经过命令行的方式传入参数。而不单单经过app.run()方法中传参,好比咱们能够经过python hello.py runserver --host ip地址,告诉服务器在哪一个网络接口监听来自客户端的链接。默认状况下,服务器只监听来自服务器所在计算机发起的链接,即localhost链接。
pip3 install Flask-Script
from flask import Flask from flask_script import Manager app = Flask(__name__) # 建立Manager管理类的对象 manager = Manager(app) @app.route("/index") def index(): return "index" if __name__ == '__main__': # app.run() # 经过管理对象来启动 manager.run()