1.flask介绍
flask:
- 轻,短小精悍
- 快,三行代码开启服务
- 自带组件少,大多数来源第三方,flask-admin,flask-session
- flask大版本更新,组件更新速度慢
django:
- 大而全,admin,models,Form,中间件
- 一个框架解决所有问题
- 一旦启动,所有资源全部加载
- 太大,结构复杂
- 所有组件都有django组件自身控制
tornado:
- 原生websocket
- 异步IO
- 非阻塞
- 几乎无三方及原生组件,连session都不支持
flask常用扩展包
Flask-SQLalchemy:操作数据库; Flask-script:插入脚本; Flask-migrate:管理迁移数据库; Flask-Session:Session存储方式指定; Flask-WTF:表单; Flask-Mail:邮件; Flask-Bable:提供国际化和本地化支持,翻译; Flask-Login:认证用户状态; Flask-OpenID:认证; Flask-RESTful:开发REST API的工具; Flask-Bootstrap:集成前端Twitter Bootstrap框架; Flask-Moment:本地化日期和时间; Flask-Admin:简单而可扩展的管理接口的框架
2.开启flask
2.1简单运行 ----->(先通过终端安装flask(版本号1.0.2))
尝试运行:
from flask import Flask
app = Flask(__name__) # 模块名称将会作为单独应用启动还是作为模块启动而有不同,只有这么起名,Flask才知道去哪里找模板,静态文件等
@app.route("/") # 使用route装饰器告诉Flask什么样的URL可以出发我们的视图函数
def index():
return "hello flask"
# 这里常规写法还是加上if __name__ == "__main__"比较好,确保服务器只会在该脚本被python解释器执行的时候运行,而非作为模板导入的时候
效果

3.render_template,redirect,HttpResponse,jsonify
3.1 HttpResponse
@app.route("/")
def index():
return "hello flask" # 这里的return等同HttpResponse,直接返回字符串
3.2 Redirect
和django中的一样,用于重定向
from flask import Flask,redirect
app = Flask(__name__)
@app.route('/index')
def index():
return redirect("/") # 跳转到根目录页面
@app.route('/')
def main():
return "ok"
if __name__ == "__main__":
app.run("0.0.0.0",5005,debug=True)
当我们访问url: http://127.0.0.1:5000/index的时候,它会触发redirect("/")跳转到该地址,并触发对应的视图函数main
3.3 render_template
这里的render_template等同我们django中的render,不过在此我们需要创建一个html标签来接收
这里需要创建一个在同级目录下创建一个templates文件(必须叫它,源码规定),用于存放我们的html标签
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/index')
def index():
return render_template("index.html")
if __name__ == "__main__":
app.run("0.0.0.0",5005,debug=True)
说明:
这里一般需要指定我们的templates路径,否则会飘黄,因为模板语言采用的是jinja2,而django采用的模板语言是django,我们需要进行设置,或者选择在setting中设置

3.4 jsonify
使用 Flask 写一个接口时候需要给客户端返回 JSON 数据,在 Flask 中可以直接使用 jsonify 生成一个 JSON 的响应
from flask import Flask,jsonify
app = Flask(__name__)
# 返回JSON
@app.route('/demo')
def demo():
json_dict = {
"user_id": 10,
"user_name": "laowang"
}
return jsonify(json_dict)
if __name__=="__main__":
app.run(debug=True)
效果:

# 不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,如果是 JSON 需要指定 content-type:application/json
4. 关于request
4.1 简单说明
django的接口是依据uwsgi
flask依赖一个实现wsgi协议的模块:werkzeug
flask使用了werkzeug库中的Map和Rule来管理url与处理函数映射关系
它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等。
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
@Request.application
def hello(request):
print(request) # <Request 'http://localhost:4000/' [GET]>
print(request.method) # GET
print(request.url) # http://localhost:4000/
print(dir(request)) # 获取所有的方法
return Response('Hello World!')
if __name__ == '__main__':
run_simple('localhost', 4000, hello) # 执行该函数
4.2 request下常用参数说明:
request.method
# 前端用什么方式提交,常见是GET和POST
request.form
# Form表单中传递过来的值使用 request.form 中拿到,打印request.form,值 ImmutableMultiDict([('user', 'learning'), ('pwd', '666')]),可看做成字典
request.args
# url中传递的参数,即get请求中问号结尾后面的数据,类似django中的request.get,原始样式ImmutableMultiDict([('id', '2')])
reques.values
# 获取所有参数,打印值 CombinedMultiDict([ImmutableMultiDict([('id', '1'), ('age', '20')]), ImmutableMultiDict([('user', 'learning'), ('pwd', '666')])])
# 它可以通过打印 request.values.to_dict() 把值全部转化成字典形式
# 从这里可以看出,有些情况下url中的key和form中的key会重名,此时会出现覆盖的情况,生产环境中一定要注意该情况(form中的key会覆盖url中的key)
request.cookies
# 存在浏览器端的字符串儿也会一起带过来
request.heads
# 获取请求的请求头
request.data
# 将处理不了的数据类型转换成json存入data中 # 数据类型参考手册
request.files
# 遇到文件上传,request.files 里面存的是你上传的文件
request.path
# 获取当前的url路径
request.url
# 当前url的全部路径
request.script_root
# 当前url路径的上一级路径
request.url_root
# 当前url的路径的上一级全部路径
request.json
# 如果在请求中写入了 "application/json" 使用 request.json 则返回json解析数据, 否则返回 None
获取参数request.args的使用
from flask import Flask,request
app = Flask(__name__)
@app.route('/flask/')
def index():
id = request.args.get('id')
return '获取id是%s'% id
if __name__ == "__main__":
app.run(debug=True)
效果

request.file上传文件说明
- 一个 <form> 标签被标记有 enctype=multipart/form-data ,并且在里面包含一个 <input type=file> 标签。
- 服务端应用通过请求对象上的 files 字典访问文件。
- 使用文件的 save() 方法将文件永久地保存在文件系统上的某处。
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>欢迎登陆</h4>
<form action="/req" method="post" enctype="multipart/form-data">
<p>
<input type="file" name="file">
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
# 前端页面必须设置enctype="multipart/form-data",否则提交时会报错
app.py
from flask import Flask
from flask import render_template
from flask import request
app = Flask(__name__)
@app.route("/login")
def login():
return render_template("login.html")
@app.route("/req",methods=["POST","GET"])
def home():
print(request.files) # ImmutableMultiDict([('file', <FileStorage: '5.jpg' ('image/jpeg')>)])
print(request.files["file"]) # <FileStorage: '5.jpg' ('image/jpeg')>
my_file = request.files["file"]
print(type(my_file)) # <class 'werkzeug.datastructures.FileStorage'>
my_file.save("aa.jpg") # 这里写的有问题,图片过来名字就换了,而且还需判断发送的文件类型
return "ok"
if __name__ == '__main__':
app.run(port=5990, debug=True)
# 这里写的文件保存这里写的比较粗略,详细介绍可参考源码说明
5. 关于response
视图函数中可以返回的类型:
字符串,返回的字符串其实底层将这个字符串包装成了一个‘Response’对象
元祖,和字符串一样
response及其子类
如何返回其他类型呢??这就需要我们自定义一个Response对象,他继承自Response,套用了多继承下BaseResponse的force_type方法
from flask import Flask,url_for,Response,jsonify
app = Flask(__name__)
class JsonResponse(Response):
@classmethod
def force_type(cls, response, environ=None):
'''
这个方法只有视图函数返回非字符、非元祖、非Response对象才会调用
'''
#把字典转换成json
if isinstance(response,dict):
#jsonify将字典转换成json对象,还将该对象包装成了一个Response对象
response = jsonify(response)
return super(JsonResponse, cls).force_type(response,environ)
app.response_class = JsonResponse # 指定app.response_class为你自定义的Response对象
@app.route('/list1/')
def list1():
return Response('list1') #合法对象,可以直接返回
@app.route('/list3/')
def list3():
return {'username':'learning','age':22} #返回的是非字符非元祖非Response对象,执行force_type方法
if __name__ == "__main__":
app.run(port=5225,debug=True)
效果

6. 关于__name__的说明
app1下:
import app2
print("这在app1中",__name__)
app2下:
print("app2",__name__)
这里我在app1下打印:

# 这里需要强调的是,如果是在自己的文件下,__name__就是__main__,如果是从其他文件导入进来,则__name__就是它的文件名
来源:https://www.cnblogs.com/LearningOnline/p/9590089.html