文章目录
- Flask入门
- 第一个Flask程序
- URL与函数的映射(动态路由)
- 自定义转换器
- 查询参数的获取
- 获取表单参数
- 上传文件
- 其他参数
- url_for函数
- 使用url_for函数原因
- 响应
- flask中重定向
- 响应内容
- 自定义响应
Flask入门
Flask的介绍 Flask 是一款发布于2010年非常流行的 Python Web 框架。
特点
- 微框架、简洁,给开发者提供了很大的扩展性。
- Flask和相应的插件写得很好,用起来很爽。
- 开发效率非常高,比如使用 SQLAlchemy 的 ORM 操作数据库可以节省开发者大量书写 sql 的时间。
Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮 件扩展 Flask-Mail ,用户认证 Flask-Login ,数据库 Flask-SQLAlchemy ),都需要 用第三方的扩展来实现。
扩展列表:http://flask.pocoo.org/extensions/
- 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:简单而可扩展的管理接口的框架
文档地址
1 中文文档(http://docs.jinkan.org/docs/flask/)
2 英文文档(http://flask.pocoo.org/docs/1.0/)
Flask的安装
pip install flask
第一个Flask程序
学过Java的同学应该都知道,介不就是SpringMVC那一套吗
只不过不用引入那么多东西了,直接引入一个flask框架就行了
# 从flask包中导入Flask类
from flask import Flask
# 创建一个Flask对象
app = Flask(__name__)
# @app.route:是一个装饰器
# @app.route('/')就是将url中 / 映射到hello_world设个视图函数上面
# 以后你访问我这个网站的 / 目录的时候 会执行hello_world这个函数,然后将这个函数的返回值返回给浏览器
@app.route('/')
def hello_world():
return 'Hello Flask'
# 启动这个WEB服务
if __name__ == '__main__':
# 开启debug
# app.debug = True
# 默认为5000端口
app.run() # app.run(port=8000)
flask调试模式
app.run(debug = True)
app.debug = True
app.run()
URL与函数的映射(动态路由)
URL路径参数
比如,有一个请求访问的接口地址为 /users/11001
,其中 11001 实际上为 具体的请求参数,表明请求 11001 号用户的信息。
此时如何从url中提取出 11001 的数据?
@app.route('/users/<user_id>')
def user_info(user_id):
print(type(user_id))
return 'hello user{}'.format(user_id)
其中<user_id>
,尖括号是固定写法,尖括号(<>)里面默认的数据类型是字符串。
如果需要指定类型,则要写成 converter:variable ,其中 converter 就是类型名称,可以有以下几种:
- string:如果没有指定具体的数据类型,那么默认就是使用 string 数据类型。
- int:数据类型只能传递 int 类型。
- float:数据类型只能传递 float 类型。
- path:数据类型和 string 有点类似,都是可以接收任意的字符串,但是 path 可以接收路径,也就是说可以包含斜杠。
- uuid:数据类型只能接收符合 uuid 的字符串。 uuid 是一个全宇宙都唯一的字符串,一般可以用来作为表的主键。
- any:数据类型可以在一个 url 中指定多个路径。例如:
@app.route('/users/<int:user_id>')
def user_info(user_id):
print(type(user_id))
return f'正在获取 ID {user_id} 的用户信息'
@app.route('/users/<int(min=1):user_id>')
def user_info(user_id):
print(type(user_id))
return f'hello user {user_id}'
自定义转换器
如果遇到需要匹配提取 /sms_codes/1688888888
中的手机号数据,Flask内置的转换器就无法满足需求,此时需要自定义转换器。
自定义转换器主要做3步:
- 创建转换器类,保存匹配时的正则表达式
from werkzeug.routing import BaseConverter
class MobileConverter(BaseConverter):
"""
手机号格式
"""
regex = r'1[3-9]\d{9}'
- 将自定义的转换器告知Flask应用
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters['mobile'] = MobileConverter
- 在使用转换器的地方定义使用
@app.route('/sms_codes/<mobile:mob_num>')
def send_sms_code(mob_num):
return 'send sms code to {}'.format(mob_num)
to_python
在转换器类中,实现 to_python(self,value) 方法,这个方法的返回值,将会 传递到 view函数中作为参数
to_url
在转换器类中,实现 to_url(self,values) 方法,这个方法的返回值,将会在 调用url_for函数的时候生成符合要求的URL形式。
from werkzeug.routing import BaseConverter
class LiConverter(BaseConverter):
# 1.在转换器类中,实现to_python(self,value)方法,这个方法的返回值,将会传递到 view函数中作为参数。
def to_python(self, value):
return value.split('+') # 可以对value进行加工后再返回
# 2.在转换器类中,实现to_url(self,values)方法,这个方法的返回值,将会在调用url_for函数的时候生成符合要求的URL形式。
def to_url(self, value):
# return "hello"
# ['hots','enter']---->hots+enter
return "+".join(value)
一句话总结:转换器和Java中的拦截器有异曲同工之处,可以在请求到达处理器之前进行一些操作、如记录日志、鉴权等
查询参数的获取
通过request.values参数或者request.args参数都可以获得get请求传递的参数
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def index():
wd = request.args.get('wd')
ie = request.values.get('ie')
return f"Hello! {wd} == {ie}"
if __name__ == '__main__':
app.run(debug=True)
获取表单参数
request.form.get或者request.values.get都可以获得表单中的参数
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def index():
wd = request.args.get('wd')
ie = request.values.get('ie')
return f"Hello! {wd} == {ie}"
@app.route('/', methods=['POST'])
def post():
uname = request.form.get('uname')
pwd = request.values.get('pwd')
age = request.form.get('age')
return f"Hello! {uname} == {pwd} == {age}"
if __name__ == '__main__':
app.run(debug=True)
上传文件
通过request.files[‘pic’]获得请求中字段为pic的文件,命名为f
之后直接调用save方法保持文件到服务器
@app.route('/upload', methods=['POST'])
def upload_file():
# f是一个代表上传文件的对象,你可以使用它来操作上传的文件。
# request.files是一个字典,用于访问上传的文件。在这里,['pic']表示你正在访问名为'pic'的上传文件字段。
f = request.files['pic']
f.save('./demo.png')
return '上传成功!'
其他参数
如果想要获取其他地方传递的参数,可以通过Flask提供的request对象来读取。
不同位置的参数都存放在request的不同属性中
url_for函数
一般我们通过一个 URL就可以执行到某一个函数。 如果反过来,我们知道一个函数,怎么去获得这个 URL呢?
url_for
函数就可以帮我们实现这个功能
注意 url_for 函数可以接收1个及以上的参数,他接收函数名作为第一个参数 如果还出现其他的参数,则会添加到 URL 的后面作为查询参数。
from flask import Flask, request, url_for
app = Flask(__name__)
@app.route('/post/list/<page>/')
def my_list(page):
return 'my list'
@app.route('/')
def hello_world():
return url_for('my_list', page=2, num=8)
# return "/post/list/2?num=8"
if __name__ == '__main__':
app.run(debug=True)
使用url_for函数原因
下图很形象的展示了原因:
- 当你有新功能想使用同一个接口,可以直接使用url_for去指定,不在需要去写新接口了
- url_for() 函数会转义一些特殊字符和 unicode 字符串,这些事情 url_for 会自动的帮我们
@app.route('/login/')
def login():
return 'login'
@app.route('/')
def hello_world():
return url_for('login', next='/')
# /login/?next=/
# 会自动的将/编码,不需要手动去处理。
# url=/login/?next=%2F
响应
- 301,永久重定向
- 302,临时重定向
- 304,缓存重定向
Java老八股文了,没啥说的
flask中重定向
重定向是通过 redirect(location,code=302) 这个函数来实现的, location表示 需要重定向到的 URL, 应该配合之前讲的 url_for() 函数来使用, code 表示采用哪个重定向,默认是 302 也即 暂时性重定向, 可以 修改成 301 来实现永久性重定向
from flask import Flask, request, url_for, redirect
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/login/')
def login():
return '这是登录页面'
# falsk中重定向
@app.route('/profile/')
def proflie():
if request.args.get('name'):
return '个人中心页面'
else:
# return redirect(url_for('login'))
return redirect(url_for('login'), code=302)
if __name__ == '__main__':
app.run(debug=True)
响应内容
1.返回字符串
@app.route('/return_str')
def return_str():
return "你好,少年"
2.返回JSON
@app.route('/json')
def return_json1():
json_dict = {
"msg_int": 10,
"msg_str": "你好,少年"
}
return json_dict
@app.route('/return_json1')
def return_json1():
json_dict = {
"msg_int": 10,
"msg_str": "你好,少年"
}
return jsonify(json_dict)
3. 返回元组
可以返回一个元组,元组中必须至少包含一个项目,且项目应当由(response, status) 、 (response, headers) 或者 (response,status, headers) 组成。
status的值会重载状态代码, headers 是一个由额外头部值组成的列表 或字典status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。
@app.route('/demo1')
def demo1():
return '状态码为 666', 666, {'itbaizhan': 'Python'}
自定义响应
创建Response
from flask import Response
@app.route('/return_str')
def return_str():
return Response("你好,少年")
make_response方式
@app.route('/demo2')
def demo2():
resp = make_response('make response测试')
resp.headers['itbaizhan'] = 'Python'
resp.status = '404 not found'
return resp