Flask的安装和入门:配置、路由、转换器、获取请求数据、重定向和报错等
前文,查看flask中文文档: http://docs.jinkan.org/docs/flask/quickstart.html
环境:python3.5,Flask1.0.3
Flask和Django的区别
-
Django原理是客户端发送请求-nginx–uwsgi–中间件–url路由–view视图函数–orm–拿到数据返回到view–将数据传到模板—中间件–uwsgi—nginx–前端渲染
-
Flask当客户端想要获取资源时,通过浏览器发起HTTP请求,此时,web服务器使用一种名为web服务器网关接口的WSGI协议,把来自客户端的请求都交给Flask程序实例,Flask使用werkzeug来做路由分发,根据每个URL请求找到具体的视图函数,获取数据后,把数据传入HTML模板文件中,jinja2模板引擎负责渲染HTTP响应数据,然后由Flask返回响应数据给浏览器
安装Flask
我们使用虚拟环境运行flask,如果没有虚拟环境就安装虚拟环境:
- sudo pip install virtualenv
- 虚拟环境可以搭建独立的python运行环境, 使得单个项目的运行环境与其它项目互不影响.
- 有的话直接创建一个虚拟环境:
- mkvirtualenv flask_py3 -p python3
然后pip install Flask直接安装Flask
pip list查看安装了哪些东西:
Package Version
------------- -------
Click 7.0
Flask 1.0.3
itsdangerous 1.1.0
Jinja2 2.10.1
MarkupSafe 1.1.1
pip 19.1.1
pkg-resources 0.0.0
setuptools 41.0.1
Werkzeug 0.15.4
wheel 0.33.4
开始一个flask应用
可以直接创建一个py文件或者开启一个project,选择对应的虚拟环境和python版本以及项目路径,然后创建会自动生成
这里可以使用自己写:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
把它保存为 hello.py (或是类似的),然后用 Python 解释器来运行。
$ python hello.py
- Running on http://127.0.0.1:5000/
现在访问 http://127.0.0.1:5000/ ,你会看见 Hello World 问候。
那么,这段代码做了什么?
- 首先,我们导入了 Flask 类。这个类的实例将会是我们的 WSGI 应用程序。
- 接下来,我们创建一个该类的实例,第一个参数是应用模块或者包的名称。 如果你使用单一的模块(如本例),你应该使用 name,因为模块的名称将会因其作为单独应用启动还是作为模块导入而有不同( 也即是 ‘main’ 或实际的导入名)。这是必须的,Flask 才知道到哪去找模板、静态文件等等。详情见 Flask 的文档。
- 然后,我们使用 route() 装饰器告诉 Flask 什么样的URL 能触发我们的函数。
- 这个函数的名字也在生成 URL 时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息。
- 最后我们用 run() 函数来让应用运行在本地服务器上。 其中 if name == ‘main’:确保服务器只会在该脚本被 Python 解释器直接执行的时候才会运行,而不是作为模块导入的时候。
- Ctrl+C退出
配置
1.直接在app.run方法里面写
2.写成类,然后app.config.from_object(MyConfig)加载:
# 写一个配置类
class MyConfig(object):
DEBUG = True
PORT = 6000
3.从文件导入配置,创建一个config.ini配置文件里面写配置内容,然后设置即可:
- app.config.from_pyfile(‘config.ini’)
4.还有其他的自己研究
app的一些参数
- app.url_map:查看所有路径对应内容
- app.run(host=‘0.0.0.0’):这会让操作系统监听所有公网 IP。
调试模式
虽然 run() 方法适用于启动本地的开发服务器,但是你每次修改代码后都要手动重启它。这样并不够优雅,而且 Flask 可以做到更好。如果你启用了调试支持,服务器会在代码修改后自动重新载入,并在发生错误时提供一个相当有用的调试器。
有两种途径来启用调试模式。一种是直接在应用对象上设置:
- app.debug = True
- app.run()
另一种是作为 run 方法的一个参数传入:
- app.run(debug=True)
路由
注意/严格匹配,前/和后/都要注意
@app.route('/')
def index():
pass
# 带参数
@app.route('/<username>')
def show_user(username):
pass
# 指定格式的参数
@app.route('/post/<int:post_id>')
def show_post(post_id):
pass
第1个路由:捕获到 “/”,就进入函数进行处理,里面的函数叫做视图函数。URL从左到右第一个“/”为止一般 是首页,因此第1一个路由是处理首页。
第2个路由:捕获到 “/” ,其中尖括号<…> 这一部分是动态可变的部分,其中不可以带有斜杠的。而且这个动态部分当做参数传递给了视图函数。
第3个路由:捕获到 “/post/int:post_id” 其中 “/post/”是静态部分,“int:post_id”是动态部分,但是这个动态部分必须是个int类型的整数,同样其中不可以带有斜杠。同样这个动态部分也成为参数传入了视图函数show_post。这个rule是 converter:name的形式,而converter除了有int,还有float,path,string。
转换器类型:
- string(缺省值)接受任何不包含斜杠的文本
- int 接受正整数
- float 接受正浮点数
- path 类似 string ,但可以包含斜杠
- uuid 接受 UUID 字符串
还可以为同一个视图函数,定义多个URL规则:
这指定/users/将是第1页的URL,并且 /users/page/N将是第N页的URL
@app.route('/user/', defaults={'page':1})
@app.route('/user/page/<int:page>')
def show_user(page):
return 'user page : %s' % page
HTTP的请求方法
可以使用 route() 装饰器的 methods 参数来处理不同的 HTTP 方法:
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return 'POST'
else:
return 'GET'
如果当前使用了 GET 方法, Flask 会自动添加 HEAD 方法支持,并且同时还会 按照 HTTP RFC 来处理 HEAD 请求。同样, OPTIONS 也会自动实现。
返回json类型
不能返回dict字典类型,只能是string,tuple等类型,所以用flask带的jsonify转换json类型然后返回
- jsonify转的字典里面要是双引号
from flask import jsonify
@app.route('/')
def index():
data = {
"name": "小明",
"age": 18,
}
return jsonify(data)
获取请求数据
注意这里是自己请求发送对应的数据
@app.route('/index/', methods=['POST', 'GET'])
def postget():
if request.method == 'POST':
print(request.headers) # 获取请求头
# args接收get请求后面?name=hhh&age=18的数据
print(request.args)
# json可以获取ajax发送的json数据
print(request.json)
# print(request.args['name'])
print(request.data) # 获取请求的二进制数据,图片
# form只能接收表单发过来的text数据
print(request.form)
# print(request.form['name']) # 这就是获取请求中的表单数据
# form表单发送的file文件用fiels获取,类型为字典
file = request.files['areas']
# 表单的file文件转bytes类型
data = request.files.get('img').read()
# 保存到static文件夹
file.save('./static/areas.sql')
print(file)
return 'POST'
return 'GET'
转换器
默认的转换器:
自定义转换器
- 系统自带的没有正则匹配,所以需要自己写
- 继承于BaseConverter,需要调用父类的初始化
- 在url添加额外的参数(正则表达式),然后赋值给自带的regex属性即可
- 最后加入到转换器字典中
from werkzeug.routing import BaseConverter
class MyConverter(BaseConverter):
def __init__(self, map, *args, **kwargs):
# 只需要重新赋值regex就行
# args第一个参数就是正则表达式
self.regex = args[0]
super().__init__(map)
# 加入到默认转换器字典中
app.url_map.converters['re'] = MyConverter
@app.route('/<re("[a-z]{4}"):name>')
def index(name):
data = {
"name": name,
"age": 18,
}
return jsonify(data)
重定向和报错
使用 redirect() 函数可以重定向。使用 abort() 可以主动报错,参数填要抛出的错误比如404:
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('error'))
@app.route('/error')
def error():
abort(401)
this_is_never_executed()
上例实际上是没有意义的,它让一个用户从索引页重定向到一个无法访问的页面(401 表示禁止访问)。但是上例可以说明重定向和出错跳出是如何工作的。
缺省情况下每种出错代码都会对应显示一个黑白的出错页面。使用 errorhandler() 装饰器可以定制出错页面:
自定义出错内容
用装饰器,装饰器参数填404,401或者导包然后exception的属性选择对应的出错内容,比如这里用的是401对应Unathorized,400对应BadRequest:
from werkzeug import exceptions
# 自定义错误处理:用装饰器或者app注册
@app.errorhandler(exceptions.Unauthorized)
def handle_error(e):
return 'ooooooo bad', 401
或者用app注册来设置错误时返回的代码:
# 自定义错误处理:用app注册
def handle_error(e):
return 'ooooooo bad', 401
app.register_error_handler(401, handle_error)