python之初识Flask
Posted 勿忘初心、继续前行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之初识Flask相关的知识,希望对你有一定的参考价值。
一、初识Flask
Python三大主流Web框架对比
1、三大框架的特点
- Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不管你用得到用不到,反正它全都有,属于全能型框架
- Tornado 主要特点是原生异步非阻塞,在IO密集型应用和多任务处理上占据绝对性的优势,属于专注型框架
- Flask 主要特点小而轻,原生组件几乎为0, 三方提供的组件请参考Django 非常全面,属于短小精悍型框架
2、三大框架的优缺点
- Django 通常用于大型Web应用由于内置组件足够强大所以使用Django开发可以一气呵成
- Tornado 通常用于API后端应用,游戏服务后台,其内部实现的异步非阻塞真是稳得一批
- Flask 通常应用于小型应用和快速构建应用,其强大的三方库,足以支撑一个大型的Web应用
- Django 优点是大而全,缺点也就暴露出来了,这么多的资源一次性全部加载,肯定会造成一部分的资源浪费
- Tornado 优点是异步,缺点是干净,连个Session都不支持
- Flask 优点是精悍简单,缺点是组件大都来自第三方等
关于上面的总结
Django:
优点:
大而全,admin,models,Form,中间件,session
一个框架解决所有问题
缺点:
一旦启动,所有资源全部加载,用不到的,浪费了
太大了,结构复杂
所有的组件,全部由Django自身控制
Flask:
优点:
轻、短小精悍
快、最短三行代码就能开启服务
缺点:
组件大部分都来自第三方,如flask-admin, flask-session
flask大版本更新,组件更新速度慢
Tornado:
优点:
原生的websocket
异步io
非阻塞
缺点:
三方和原组件几乎为零
Flask的准备工作
首先我们要安装Flask,具体操作如下:
pip install Flask
也可以通过pycharm在里面直接搜索Flask点击安装就好。还有其他的一些安装在这里就不在说了
三行代码启动Flask
from flask import Flask app = Flask(__name__) app.run()
执行上面的代码我么在控制台可以看到一下一行代码
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
从上面可以看出默认访问的端口是5000,
我们访问该页面
上面给我的提示是没有相应的路由,因为我们根本没有配置,不过这个时候服务已经起来了
这个就是三行代码启动Flask服务
我们来写一个真正的第一个flask程序
from flask import Flask # 导入Flask类 # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) # url与视图映射 @app.route(\'/\') # app中的route装饰器 def hello_world(): # 视图函数 return \'Hello World!\' # 返回的响应体 if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
启动上面代码并访问相应的页面我们在页面上就会看到\'Hello World\'的字样
路由系统
url传参的方式
普通的传参
@app.route(\'/user/<id>/\') # app中的route装饰器 def hello_world(id): # 视图函数 return \'你是第{}个用户\'.format(id) # 返回的响应体
指定参数类型
有以下几种参数类型:
- string:默认的数据类型
- int:接收整型
- float:浮点型
- path:和string类似,这里可以接收斜杠
- any:可以指定多个路径
- uuid:只接受uuid字符串
(1) any
@app.route(\'/<any(blog,user):url_path>/<id>/\') def detail(url_path,id): if url_path == \'blog\': return \'博客详情{}\'.format(id) else: return \'用户详情{}\'.format(id)
注意:上面的路由 \'/<any(blog,user):url_path>/<id>/\'写的时候一定要加上\'/\'反斜杠,要不会出错
(2)path
@app.route(\'/article/<path:test>/\') def test_article(test): return \'test_article:{}\'.format(test)
有上面的图片可以看出来只要是前面匹配成功了,后面所有的包含\'/\'都会当做path。
endpoint
endpoint:反向生成url
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import url_for app = Flask(__name__) # 这里的endpoint我们可以不写,不写就默认为index和函数名一样 @app.route(\'/index/\', endpoint=\'first\') def index(): print(url_for(\'first\')) # 如果上面没有穿endpoint得话就写\'index\' return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
访问:http://127.0.0.1:5000/index/
pycharm控制台得到
/index/
这个不算是完整的url要想得到完整的url我们修改后为
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import url_for app = Flask(__name__) # 这里的endpoint我们可以不写,不写就默认为index和函数名一样 @app.route(\'/index/\', endpoint=\'first\') def index(): print(url_for(\'first\',_external=True)) # 如果上面没有穿endpoint得话就写\'index\' return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
pycharm控制台输出为:
http://127.0.0.1:5000/index/
这样还是不够当我们后面有参数的时候怎么办
使用下面的方式:
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import url_for,request app = Flask(__name__) # 这里的endpoint我们可以不写,不写就默认为index和函数名一样 @app.route(\'/index/\', endpoint=\'first\') def index(): stu_id = int(request.args[\'id\']) print(url_for(\'first\', _external=True, id=stu_id)) # 如果上面没有穿endpoint得话就写\'index\' return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
访问:http://127.0.0.1:5000/index/?id=1
pycharm控制台得到的输出为:
http://127.0.0.1:5000/index/?id=1
defaults
defaults : 视图函数的参数默认值{"nid":100}
注意:视图函数必须要设置形参nid,否则报错!
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import url_for,request app = Flask(__name__) # 这里的endpoint我们可以不写,不写就默认为index和函数名一样 @app.route(\'/index/\', endpoint=\'first\', defaults={\'nid\':100}) def index(nid): stu_id = int(request.args[\'id\']) print(url_for(\'first\', _external=True, id=stu_id)) # 如果上面没有穿endpoint得话就写\'index\' print(nid) return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
访问:http://127.0.0.1:5000/index/?id=1
pycharm得到的结果为:
http://127.0.0.1:5000/index/?id=1 100
访问一个结尾不带斜线的url会被flask重定向到一个带斜线的规范url去,所以我们在写的时候还是要在路由后面加一个斜线
响应
响应体 HttpResponse、Render、Redirect、jsonify
HttpResponse
@app.route("/") # app中的route装饰器 def index(): # 视图函数 return "Hello World!" # HttpResponse
在flask中的HttpResponse 其实就是直接返回字符串
redirect
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import redirect # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) # url与视图映射 @app.route(\'/redi/\') def redi(): return redirect(\'/\') # redirect跳转至"/" @app.route(\'/\') def index(): return \'Hello Word!\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
在上面我们启动后访问: http://127.0.0.1:5000/redi/
会看到Hello World
render
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import render_template # 导入flask中的render_template # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) @app.route(\'/index/\') def index(): return render_template(\'index.html\') if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
在当前的py文件的同级目录下创建一个templates目录然后在该目录下创建一个index.html文件
index.html内容如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Hello World!</h1> </body> </html>
我们可以重启后访问后会出现一下结果
在上面我们写return render_template(\'index.html\')
会发现index.html这个飘黄我们可以在pycharm的右击templates -> Mark Directory as-->Template Folder
会跳出来一个选项选择yes就好,然后出来一个界面在右边有一个Tempalte language在后面我们选择Jinja2然后点击确定就好
如果我们使用pycharm创建一个Flask项目就不会出现这个问题,但是现阶段建议自己手动操作,有利于更好的熟悉flask
jsonify
后端代码为
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import jsonify # 导入flask中的jsonify # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) @app.route(\'/index/\') def index(): return jsonify({\'k1\':\'v1\'}) if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
访问http://127.0.0.1:5000/index/
得到下图:
定制响应头。
flask如何给自己定制一个响应头信息
后端代码为
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import make_response # make_response专门是用来设置响应头的 # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) @app.route(\'/index/\') def index(): obj = make_response(\'qwer\') obj.headers[\'aaaa\'] = \'123\' obj.set_cookie(\'key\', \'value\') return obj if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
访问:http://127.0.0.1:5000/index/
我们可以看到浏览器中信息
页面为:
点击右键选择 检查(使用的是Google Chrome)
可以看到我们在上面设置的请求头在这里能够看到
再看看我们的cookie
这个就是我们定制的响应头
request相关
每个框架中都有处理请求的机制(request),但是每个框架的处理方式和机制是不同的
为了了解Flask的request中都有什么东西,首先我们要写一个前后端的交互
基于HTML + Flask 写一段前后端的交互
先写一段儿HTML form表单中提交方式是post action地址是 /test
login.html的代码为
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎登陆</h1> <form action="/test/" method="post"> <p> <input type="text" name="user" placeholder="请输入用户名"> </p> <p> <input type="password" name="pwd" placeholder="请输入密码"> </p> <input type="submit" value="提交"> </form> </body> </html>
我们写的flask的代码为
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import render_template # 导入flask中的render_template from flask import request # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) @app.route(\'/login/\') def index(): return render_template(\'login.html\') @app.route(\'/test/\') def home(): print(request) return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
我们访问http://127.0.0.1:5000/login/页面后随便输入用户名和密码或者直接提交就会出现下面的图示
这个提示是其请求的方式不被允许。
这个请求的方式不被允许是因为默认的路由只允许GET,我们提交的是POST所以这里不通过
request.methods
修改我们的flask代码
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import render_template # 导入flask中的render_template from flask import request # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) @app.route(\'/login/\') def index(): return render_template(\'login.html\') @app.route(\'/test/\', methods=[\'POST\']) # 表示只允许POST请求 def home(): print(request) # request对象 print(request.method) print(request.form) print(request.form[\'user\']) print(request.form.get(\'pwd\')) print(request.form.keys()) for i in request.form.keys(): print(i) return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
重启后再次访问login然后输入用户名和密码都是admin,
控制台的输出为
<Request \'http://127.0.0.1:5000/test/\' [POST]> POST ImmutableMultiDict([(\'user\', \'admin\'), (\'pwd\', \'admin\')]) admin admin <dict_keyiterator object at 0x00000252AD6A0F48> user pwd
上面的@app.route(\'/test/\', methods=[\'POST\'])
后面的methods后面是列表,这个表示可以有多个值,所以我们想要允许什么的请求就在这里写上就好。
request.form
上面我们Form表单提交的数据我们可以通过request.form拿到提交的数据。
print(request.form) # ImmutableMultiDict([(\'user\', \'xiao\'), (\'pwd\', \'123\')]) # ImmutableMultiDict 它看起来像是的Dict 就用Dict的方法取值试一下吧 print(request.form["user"]) # admin print(request.form.get("pwd")) # admin # 看来全部才对了, ImmutableMultiDict 似乎就是个字典,再来玩一玩它 print(list(request.form.keys())) # [\'user\', \'pwd\'] 看来是又才对了 #如果以上所有的方法你都觉得用的不爽的话 req_dict = dict(request.form) print(req_dict) # 如果你觉得用字典更爽的话,也可以转成字典操作(这里有坑)
request.args
request.args中保存的是url中传递的参数
修改后端的GET
#!/usr/bin/env python # -*-coding:utf-8-*- from flask import Flask # 导入Flask类 from flask import render_template # 导入flask中的render_template from flask import request # 实例化一个Flask对象,传递__name__参数进去 app = Flask(__name__) @app.route(\'/login/\') def index(): return render_template(\'login.html\') @app.route(\'/test/\', methods=[\'POST\', \'GET\']) # 表示只允许POST请求 def home(): print(request.args) print(request.args[\'id\']) print(request.args.get(\'age\')) print(list(request.args.keys())) print(list(request.args.values())) req_dic = dict(request.args) print(req_dic) # print(request) # request对象 # print(request.method) # print(request.form) # print(request.form[\'user\']) # print(request.form.get(\'pwd\')) # print(request.form.keys()) # for i in request.form.keys(): # print(i) return \'ok\' if __name__ == \'__main__\': # 这里面的端口我们是可以自己设置的,我这里就没有设置了还是默认的5000 # debug=True表示启动debug模式。当代码有改动时,Flask会自动加载,无序重启!默认是关闭的 app.run(debug=True) # 启动Flask服务
然后在url地址栏输入下面的url
http://127.0.0.1:5000/test/?id=13&age=28
得到如下页面
控制台我们得到的输出是
ImmutableMultiDict([(\'id\', \'13\'), (\'age\', \'28\')]) 13 28 [\'id\', \'age\'] [\'13\', \'28\'] {\'id\': [\'13\'], \'age\': [\'28\']}
有上面的示列可以看出request.form和request.args的区别
request.form是获取form表单中的参数
request.args是获取url中参数的
request.values
前端代码改动部位为黄色
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> Flask之模板之宏继承包含