虚拟环境说明
-
想在另一台电脑同步该虚拟环境中所安装的包
-
首先把该电脑的虚拟环境中的包指定到一个文件中
pip freeze > requirements.txt
-
把该文件给需要同步的电脑,在那太电脑中先创建好一个虚拟环境
-
同步
pip install -r requirements.txt
-
Flask框架
简介 官方文档
- 它是一个轻量级的框架,只提供web框架的核心功能,比较的自由、灵活、高度定制
- 它本身相当于一个内核,其他几乎所有功能都要用到扩展,都需要第三方的扩展来实现
- Flask框架的核心:Werkzeug和Jinja2
Flask扩展包
- Flask-SQLalchemy:操作数据库
- Flask-migrate:管理迁移数据库
- Flask-Mail:邮件
- Flask-WTF:表单
- Flask-script:插入脚本
- Flask-Login:认证用户状态
- Flask-RESTful:开发REST API的工具
- Flask-Bootstrap:集成前端Twitter Bootstrap框架
- Flask-Moment:本地化日期和时间
安装
pip install flask==0.10.1
一个简单的Flask程序
# 导入Flask类
from flask import Flask
#创建flask的应用对象
app = Flask(__name__)
# 装饰器的作用是将路由映射到视图函数index
@app.route('/')
def index():
'''定义视图函数'''
return 'Hello World'
# Flask应用程序实例的run方法启动WEB服务器
if __name__ == '__main__':
app.run()
__name__
:表示当前的模块的名字@app.route('/')
:用装是器来实现路由的映射app.run()
的参数,可以传递host、port和debug
创建APP对象
- 初始化参数:
static_url_path
:static_folder
: 默认‘static’template_folder
: 默认‘templates’
Flask配置参数设置
-
法1:创建一个文件
config.cfg
(文件名随意指定),在里面设置配置,然后使用配置文件app.config.from_pyfile(“yourconfig.cfg”)
-
法2:使用对象配置参数,在程序里用一个类来定义配置参数
class Config(object): DEBUG = True app.config.from_object(Config)
-
法3:直接操作config的字典对象
app.config["DEBUG"] = True
在视图中读取配置参数
-
法1:
app.config['xxx']
、app.config.get('xxx')
(前提是配置信息在同一程序中,还有尽量用get,不然若取不到的话会报错) -
法2:若在模块中无法直接拿到app,可以用
current_app
,其用法与app 的用法一样from flask import aurrent_app aurrent_app.config.get("DEBUG")
视图函数的路由规则
-
@app.route('/post', methods=['POST'])
methods
可以指定该url可以由什么方式请求,列表,可以写多个 -
查看flask中路由的信息:app.url_map,显示形式为下
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>, <Rule '/python/<filename>' (HEAD, OPTIONS, GET) -> static>])
-
几种情况
-
①同样的url,访问不同的视图函数
当url和请求方式一样,谁在前面就访问哪个视图函数
-
不同的url,访问相同的视图函数
装饰器是可以叠加的,在同一视图函数上用不同的
@app.route
配置
-
-
Flask中的反向解析
from flask import redirect @app.route('/login') def login(): url = url_for('index') return redirect(url) # 重定向
url_for('index')
可以进行反向解析,index
是通过视图函数的名字找到视图对应的url路径 -
动态路由
@app.route('/goods/<int:goods_id>') def goods_detail(goods_id) pass
int 是一个转换器,意思就是如
127.0.0.1:5000/goods/12
匹配到int类型就符合规则,就把匹配到的值赋值自己定义的goods_id
这个变量,然后在定义视图函数时需传参goods_id
来接受数据- 几种转换器
- int:接受整数
- float:同int,但接受的是浮点数
- path:和默认的相似,但也接受斜线(默认就是普通的字符串规则,除了斜线)
- 几种转换器
-
自定义转换器
-
1.用类的方法定义
from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): """""" def __init__(self, url_map, regex): # 调用父类的初始化方法 super(RegexConverter, self).__init__(url_map) # 将正则表达式的参数保存到对象的属性中,flask会去使用这个属性来进行路由的正则匹配 self.regex = regex
-
2.将自定义的转换器添加到flask的应用中
app.url_map.converters["re"] = RegexConverter # re为你给转换器定义的名字
-
3.使用
@app.route("/send/<re(r'1[34578]\d{9}'):mobile_num>") # 因为自定义的是re的万用转换器,直接在里面写正则就好
这种情况下,使用
url_for()
不仅需要传递视图函数的名字,还需mobile_numurl = url_for("send_sms", mobile_num="18922222222")
-
获取请求参数
-
request 中包含了前端发送过来的所有请求数据,是 Flask 中表示当前请求的 request 对象,request对象中保存了一次HTTP请求的一切信息
-
request.form
可以直接提取请求体中的表单格式的数据,是一个类字典的对象通过get方法只能拿到多个同名参数的第一个,getlist获取全部
name = request.form.get("name") name_li = request.form.getlist("name")
-
如果是请求体的数据不是表单格式的(如json格式),可以通过
request.data
获取 -
args是用来提取url中的参数(查询字符串)
-
request 常用的属性
属性 说明 类型 data 记录请求的数据,并转为字符串 form 记录请求中的表单数据 MultiDict args 记录请求中的查询参数 MultiDict cookies 记录请求中的cookie信息 Dict headers 记录请求中的报文头 EnvironHeaders method 记录请求中的HTTP请求方法 GET/POST url 记录请求的URL地址 string files 记录请求上传的文件 -
在视图函数中,可能对不同的请求方式会有不同的处理,这时就可以用
if request.method == 'GET': pass elif request.method == 'POST': pass
-
上传文件
-
已上传的文件存储在内存或是文件系统中一个临时的位置,你可以通过请求对象的 files 属性访问它们。每个上传的文件都会存储在这个字典里。
-
request.files.get()
可以接受前端上传的文件@app.route("/upload", methods=["POST"]) def upload(): """接受前端传送过来的文件""" file_obj = request.files.get("pic") if file_obj is None: # 表示没有发送文件 return "未上传文件" # 直接使用上传的文件对象保存 file_obj.save("./demo1.png") return "上传成功"
自定义异常处理
-
abort()函数
-
使用abort函数可以立即终止视图函数的执行,并可以返回给前端特定的信息
from flask import Flask, request, abort, Response app = Flask(__name__) @app.route("/login", methods=["GET"]) def login(): # name = request.form.get() # pwd = request.form.get() name = "" pwd = "" if name != "zhangsan" or pwd != "admin": # 1 传递状态码信息, 必须是标准的http状态码 abort(404) # # 2. 传递响应体信息 # resp = Response("login failed") # abort(resp) return "login success"
-
-
自定义异常处理
# 定义错误处理的方法 @app.errorhandler(404) def handle_404_error(err): """自定义的处理错误方法""" # 这个函数的返回值会是前端用户看到的最终结果 return u"出现了404错误, 错误信息:%s" % err if __name__ == '__main__': app.run(debug=True)
即这个函数回去处理404页面错误,这个函数的返回值会返回给前端
-
设置响应信息
-
使用元组返回自定义的响应信息,也可以使用字典
@app.route("/index") def index(): return "index page", 400, [("Name", "Fxh"), ("Age", "21")]
index page
:响应体400
:状态码[("Name", "Fxh"), ("Age", "21")]
:响应头 -
使用make_response 来构造响应信息
@app.route("/index") def index(): resp = make_response("index page 2") resp.status = "999 说明信息" # 设置状态码,后面为你对该状态码的说明信息 resp.headers["Name"] = "Fxh" # 设置响应头 return resp
返回json数据的方法
-
json就是字符串
-
法1:直接操控json模块
import json @app.route("/index") def index(): data = {'name':'fxh','age':21} json_str = json.dumps(data) return json_str, 200, {"Content-Type": "application/json"}
json.dumps(字典)
——->Python字典转换为json字符串json.loads(字符串)
——>字符串转为Python字典
-
法2:使用 jsonify 返回 json 数据
-
jsonify帮助转为json数据,并设置响应头 Content-Type 为application/json
-
可以把data当成参数传递给jsonify ,也可以传参时直接写
return jsonify(data) ##### return jsonify(name="sz", age=21)
-
cookie的使用
-
设置cookie
from flask import Flask, make_response, request app = Flask(__name__) @app.route("/set_cookie") def set_cookie(): resp = make_response("success") # 设置cookie, 默认有效期是临时cookie,浏览器关闭就失效 resp.set_cookie("name", "fxh") # max_age设置有效期,单位:秒 resp.set_cookie("name", "fxh", max_age=3600) # cookie的添加实则就是在响应头里添加字段,所以也可以直接写进响应头里 resp.headers["Set-Cookie"] = "name=fxh; Expires=Sat, 18-Nov-2019 04:36:04 GMT; Max-Age=3600; Path=/" return resp
-
获取cookie
@app.route("/get_cookie") def get_cookie(): c = request.cookies.get("name") return c
-
删除cookie
@app.route("/delete_cookie") def delete_cookie(): resp = make_response("del success") # 删除cookie resp.delete_cookie("name") return resp
session
-
机制
-
session设置
from flask import Flask, session, current_app app = Flask(__name__) # flask的session需要用到的秘钥字符串 app.config["SECRET_KEY"] = "dhsodfhisfhosdhf29fy989" @app.route("/login") def login(): # 设置session数据 session["name"] = "fxh" session["mobile"] = "18611111111" return "login success" @app.route("/index") def index(): # 获取session数据 name = session.get("name") return "hello %s" % name
-
session默认是储存在cookie里面的,也可以存在数据库、redis、文件、程序内存里,但如果存在程序内存中(在程序中定义一个全局变量存储),最后部署服务器时,在多个服务器之间,用户有可能在1号服务器登录,然后过了会又在2号服务器登录,而两个服务器的全局变量不是同步的,这时2号服务器就没有该用户刚登录时设置的session数据,当然这种情况也可以适当的解决,比如在nginx调度时可以给它一个规则,某个地区的用户分配到哪个服务器
上下文
-
相当于一个容器,保存了Flask程序运行过程中的一些信息
-
请求上下文:request和session都属于请求上下文对象
-
request:封装了HTTP请求的内容,针对的是http请求。如:
user = request.args.get('user')
,获取的是get请求的参数 -
session:用来记录请求会话中的信息,针对的是用户信息。如:
session['name'] = user.id
,可以记录用户信息,还可以通过session.get('name')
获取用户信息 -
在Django中,request是局部变量,所以每个对象请求时都是不同的,而在Flask中,request则是全局变量,它是如何区分request对象是哪个用户的呢?
-
其实在Flask中,全局变量使用起来相当于线程局部变量,它会把建立一个request字典,然后用户A请求时,就建立一个线程A放进request中,然后线程A中保存着用户A请求发送的数据,这时如果又有一个用户B来请求时,就又会建立一个线程B来服务用户B
request = { '线程A':{ from:{'name':'xxx'} args:xxx } '线程B':{ xxxx } }
-
-
-
应用上下文:current_app和g都属于应用上下文对象
- current_app:表示当前运行程序文件的程序实例
- g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量
请求钩子
-
请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子
装饰器 功能 @app.before_first_request 在处理第一个请求前运行 @app.before_request 在每次请求前运行 @app.after_request 如果没有未处理的异常抛出,在每次请求后运行 @app.teardown_request 在每次请求后运行,即使有未处理的异常抛出 -
请求钩子在每个视图函数被请求时都会执行(类似于Django中的中间件),也可以让钩子所装饰的函数根据不同的视图函数而执行不同的程序
@app.teardown_request def handle_teardown_request(response): """在每次请求 (视图函数处理)之后都被执行, 无论视图函数是否出现异常,都被执行, 工作在非调试模式时 debug=False""" path = request.path if path == url_for("index"): print("在请求钩子中判断请求的视图逻辑: index") elif path == url_for("hello"): print("在请求钩子中判断请求的视图逻辑: hello") print("handle_teardown_request 被执行") return response
Flask-Script 扩展命令行
-
通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过
app.run()
方法中传参 -
安装:
pip install Flask-Script
-
使用:
from flask import Flask from flask_script import Manager app = Flask(__name__) #创建Manger管理类对象 manager = Manager(app) @app.route('/') def index(): pass if __name__ == "__main__": manager.run() ############### # 这时启动就可以在终端中用下面命令启动 python 该程序所在的文件名 runserver # 后面可以加--help来查看参数
- 先写这么多吧,剩下的学完在继续写
- 加油吧,每天积累一点!!!!