flask基础_1

Flask
Flask诞生于2010年,是Armin ronacher用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架。
WerkZeug
- 官方的介绍说Werkzeug是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等。Flask 框架就是基于Werkzeug 为基础开发的。
Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。
官网: https://flask.palletsprojects.com/en/1.1.x/
官方文档: http://docs.jinkan.org/docs/flask/
Flask常用第三方扩展包:
- Flask-SQLalchemy:操作数据库,ORM;
- Flask-script:终端脚本工具,脚手架;
- Flask-migrate:管理迁移数据库;
- Flask-Session:Session存储方式指定;
- Flask-WTF:表单;
- Flask-Mail:邮件;
- Flask-Bable:提供国际化和本地化支持,翻译;
- Flask-Login:认证用户状态;
- Flask-OpenID:认证, OAuth;
- Flask-RESTful:开发REST API的工具;
- Flask JSON-RPC: 开发rpc远程服务[过程]调用
- Flask-Bootstrap:集成前端Twitter Bootstrap框架
- Flask-Moment:本地化日期和时间
- Flask-Admin:简单而可扩展的管理接口的框架
可以通过 https://pypi.org/search/?c=Framework+%3A%3A+Flask 查看更多flask官方推荐的扩展
特点
- 扩展性强
- 精简小巧和简单(不存在任何组件,避免造成资源浪费,Django在启动的时候会加载很多组件)
- 支持很多三方组件
- 注意:Flask三方组件都是基于Flask源码编写的,有组织也有个人编写的(名称都是Flask开头的,例如Flask-Admin,Flask-Session),一旦项目中使用的三方组件和Flask版本不兼容则整个项目就跑不通了。
缺点
- 由于三方组件众多的原由,因此flask稳定性相对较差。例如使用老版本的Flask使用新版本的三方组件,则蹦。
准备
mkvirtualenv flask -p python3
安装
pip install flask==0.12.5
创建flask项目
小试牛刀:三行启动一个Flask服务
from flask import Flask
app = Flask(__name__) #实例化flask
app.run(debug=True)#flask对象相关操作
#debug=True:页面显示错误信息,修改代码重启服务
上述代码服务启动后访问到的是404页面,表示 qqq访问服务器成功,但是访问404没有意义,表示没有找到指定页面。我们的目的是当访问一个url地址的时候可以通过视图函数返回一个页面或者其他。
创建一个flask框架的主程序。名字可以是app.py/run.py/main.py/index.py
from flask import Flask
#实例化flask对象
app = Flask(__name__) # __name__可以是任意的小写字母,表示Flask应用对象名称
# 声明web服务的请求资源(指定资源访问的路由)
@app.route('/path', methods=['GET', 'POST', 'PUT', 'DELETE'] )
def index():
return 'Hello World'
if __name__ == '__main__':
app.run(debug=True) # flask对象调用run启动服务
flask实例化配置
"""
import_name Flask程序所在的包(模块),传 __name__ 就可以
其可以决定 Flask 在访问静态文件时查找的路径
static_path 静态文件访问路径(不推荐使用,使用 static_url_path 代替)
static_url_path 静态文件访问路径,可以不传,默认为:/ + static_folder
static_folder 静态文件存储的文件夹,可以不传,默认为 static
template_folder 模板文件存储的文件夹,可以不传,默认为 templates
"""
app = Flask(import_name=__name__)
flask对象配置
#app.run(debug=True):也是一种对象配置,可以换成另一种方式:app.config['DEBUG'] = True
from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = True
@app.route('/')
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()#可进行对象配置
上述的配置都是flask将常用的配置进行了简化(并不是所有的配置都有其简化的形式),除此之外还有一个标准万能的配置形式:
from flask import Flask
app = Flask(import_name=__name__)
# 加载项目配置
class Config(object):
# 开启调试模式
DEBUG = True
app.config.from_object( Config )
@app.route('/')
def index():
return "<h1>hello world</h1>"
if __name__ == '__main__':
# 运行flask:注意host和port只可以配置在run中
app.run(host="0.0.0.0", port=5000)
路由的基本定义
路由和视图的名称必须全局唯一,不能出现重复,否则报错。
# 指定访问路径为 demo1
@app.route('/demo1')
def demo1():
return 'demo1'
url中可以传递路由参数, 2种方式
路由参数就是url路径的一部分。
任意路由参数接收
# 路由传递参数[没有限定类型]
@app.route('/user/<user_id>')
def user_info(user_id):
return 'hello %s' % user_id
限定路由参数接收
通过路由转换器限定路由参数的类型,flask系统自带转换器编写在werkzeug.routing.py文件中。底部可以看到以下字典:
DEFAULT_CONVERTERS = { "default": UnicodeConverter, "string": UnicodeConverter, "any": AnyConverter, "path": PathConverter, "int": IntegerConverter, "float": FloatConverter, "uuid": UUIDConverter, }系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。
| 转换器名称 | 描述 |
|---|---|
| string | 默认类型,接受不带斜杠的任何文本 |
| int | 接受正整数 |
| float | 接受正浮点值 |
| path | 接收string但也接受斜线 |
| uuid | 接受UUID(通用唯一识别码)字符串 xxxx-xxxx-xxxxx-xxxxx |
代码:
# flask提供了路由转换器可以让我们对路由参数进行限定
# 路由传递参数[限定数据类型]
@app.route('/user/<int:user_id>')
def user_info(user_id):
return 'hello %d' % user_id
自定义路由参数转换器
也叫正则匹配路由参数.
在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问
具体实现步骤为:
- 导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录
- 自定义转换器:自定义类继承于转换器基类
- 添加转换器到默认的转换器字典中
- 使用自定义转换器实现自定义匹配规则
代码实现
- 导入转换器基类
from werkzeug.routing import BaseConverter
- 自定义转换器(无参)
# 自定义正则转换器
from werkzeug.routing import BaseConverter
class MyintConverter(BaseConverter):
def __init__(self,map,*args):
super().__init__(map)
# 正则参数(匹配手机号)
self.regex = '1[3,5,4,7,8]\d{9}'s
#添加转换器到默认的转换器字典中,并指定转换器使用时名字为
app.url_map.converters['my_int'] = MyintConverter
# 使用转换器去实现自定义匹配规则
@app.route("/int/<my_int:num>")
def index(num):
return num
- 自定义转换器(带参)
# 自定义正则转换器
from werkzeug.routing import BaseConverter
class RegexConverter(BaseConverter):
def __init__(self,map,*args):
super().__init__(map)
# 正则参数
self.regex = args[0]
- 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
app.url_map.converters['re'] = RegexConverter
- 使用转换器去实现自定义匹配规则
- 当前此处定义的规则是:手机号码
# 正则匹配路由
@app.route("/login/<re('1\d{10}'):mobile>")
def login(mobile):
return mobile
运行测试:http://127.0.0.1:5000/login/1311111111 ,如果访问的url不符合规则,会提示找不到页面
课堂代码:
from flask import Flask,request
# 初始化
app = Flask(import_name=__name__)
# 编写路由视图
@app.route(rule='/')
def index():
return "<h1>hello world!</h1>"
# 关于路由参数的限制,flask内置的类型不够具体,在开发中,我们经常接受参数,需要更加精确的限制
# 这时候,可以使用正则匹配路由参数
# 正则匹配路由参数,其实就是扩展flask内置的路由限定类型,需要完成4个步骤
# 1. 引入flask的路由转换器
from werkzeug.routing import BaseConverter
# 2. 创建自定义路由转换器
class MobileConverter(BaseConverter):
"""手机号码类型限制"""
def __init__(self,map,*args):
super().__init__(map)
self.regex = "1[3-9]\d{9}"
# 3. 把自定义转换器添加到flask默认的转换器字典中,也就是和原来的int,float等放在一块
app.url_map.converters['mob'] = MobileConverter
# 4. 类似原来的路由参数限制一样,调用自定义转换器名称即可
@app.route(rule='/user/<mob:mobile>')
def user(mobile):
return mobile
# 1. 引入flask的路由转换器
from werkzeug.routing import BaseConverter
# 2. 创建自定义路由转换器
class RegexConverter(BaseConverter):
"""根据正则进行参数限制"""
def __init__(self,map,*args):
super().__init__(map)
self.regex = args[0]
# 3. 把自定义转换器添加到flask默认的转换器字典中,也就是和原来的int,float等放在一块
app.url_map.converters['re'] = RegexConverter
# 4. 类似原来的路由参数限制一样,调用自定义转换器名称即可
@app.route(rule='/user/<re("\w+@\w+\.\w+"):email>')
def user2(email):
print(app.url_map) # 获取所有的路由列表
return email
# 声明和加载配置
class Config():
DEBUG = True
app.config.from_object(Config)
if __name__ == '__main__':
# 运行flask
app.run(host="0.0.0.0")
路由限定请求方式
from flask import Flask,request
# 限制客户端的http请求方法,注意这里与django不一样,flask并没有默认没有内置csrf攻击防范
@app.route(rule="/user", methods=["post","put","get","delete","patch"])
def user():
print(request.url)
return request.method
http的请求与响应
请求
文档: http://docs.jinkan.org/docs/flask/api.html#flask.request
- request:flask中代表当前请求的
request 对象 - 作用:在视图函数中取出本次请求数据
- 导入:
from flask import request - 代码位置:from flask.app import Request
常用的属性如下:
| 属性 | 说明 | 类型 |
|---|---|---|
| data | 记录请求体的数据,并转换为字符串 只要是通过其他属性无法识别转换的请求体数据 最终都是保留到data属性中 |
bytes类型 |
| form | 记录请求中的html表单数据 | MultiDict |
| args | 记录请求中的查询字符串,也可以是query_string | MultiDict |
| cookies | 记录请求中的cookie信息 | Dict |
| headers | 记录请求中的请求头 | EnvironHeaders |
| method | 记录请求使用的HTTP方法 | GET/POST |
| url | 记录请求的URL地址 | string |
| files | 记录请求上传的文件列表 | * |
| json | 记录ajax请求的json数据 | json |
获取请求中各项数据
获取查询字符串:
1.request.args:返回ImmutableMultiDict对象,该对象内部存储了接收到的查询字符串的数据
- ImmutableMultiDict是一个由flask封装的字典类,在字典的基础上,提供了一些其他的方法而已。
- ImmutableMultiDict([('键', '值'), ('键', '值')])
- 注意:可以出现两个名字一样的查询字符串,request也可以成功的接收到
2.ImmutableMultiDict提供的常用的方法:
- get,getlist方法,获取指定键的1个值或多个值
- to_dict方法可以将ImmutableMultiDict转换成字典
- 注意:如果args中有多个名字一样的查询字符串,则转换成字典的时候会造成数据的丢失。
获取表单中的数据:
和获取查询字符串类似
示例代码:
from flask import Flask,request
# 初始化
app = Flask(import_name=__name__)
# 编写路由视图
@app.route(rule='/')
def index():
return "<h1>hello world!</h1>"
"""== 获取查询字符串 =="""
@app.route(rule="/args",methods=["post","get"])
def args():
print(request.args) # 获取查询字符串
"""
请求地址:
http://127.0.0.1:5000/args?name=xiaoming&password=123&lve=swimming&lve=shopping
打印效果:
ImmutableMultiDict([('name', 'xiaoming'), ('password', '123')])
ImmutableMultiDict是一个由flask封装的字典类,在字典的基础上,提供了一些其他的方法而已。
格式:
ImmutableMultiDict([('键', '值'), ('键', '值')])
字典本身不支持同名键的,ImmutableMultiDict类解决了键同名问题
操作ImmutableMultiDict,完全可以操作字典操作,同时还提供了get,getlist方法,获取指定键的1个值或多个值
to_dict()
ti_list()
"""
print(request.args["name"]) # xiaoming
print(request.args.get("name")) # xiaoming
print(request.args.getlist("lve")) # ['swimming', 'shopping']
# 把ImmutableMultiDict转换成普通字典
print(request.args.to_dict(flat=False)) # {'name': ['xiaoming'], 'password': ['123'], 'lve': ['swimming', 'shopping']}
print(request.args.to_dict(flat=True)) # {'name': 'xiaoming', 'password': '123', 'lve': 'swimming'}
return "ok"
"""== 获取请求体数据 =="""
@app.route(rule="/data",methods=["post","put","patch"])
def data():
"""接受客户端发送过来的请求体数据,是request.json,request.form,request.files等无法接受的数据,全部会保留到这里"""
print(request.data) #
# 接受表单提交的数据
print(request.form) # ImmutableMultiDict([('username', 'root'), ('password', '123456')])
# 接受ajax或其他客户端提交过来的json数据
print(request.json) # {'username': 'root', 'password': '123456'}
# 接受上传文件
avatar = request.files["avatar"] # ImmutableMultiDict([('avatar', <FileStorage: '123.jpg' ('image/jpeg')>)])
print(avatar) # <FileStorage: '123.jpg' ('image/jpeg')>
# 获取请求头信息
print( request.headers ) # 获取全部的而请求头信息
print( request.headers.get("Host") )
# 获取自定义请求头
print( request.headers.get("company") ) # oldboy
print( request.headers["company"] ) # oldboy
# 本次请求的url地址
print( request.url) # http://127.0.0.1:5000/data
print( request.path ) # /data
return "ok"
# 声明和加载配置
class Config():
DEBUG = True
app.config.from_object(Config)
if __name__ == '__main__':
# 运行flask
app.run(host="0.0.0.0")
响应
flask默认支持2种响应方式:
- 数据响应: 默认响应html文本,也可以返回 JSON格式,或其他格式
- 页面响应: 重定向
make_response
make_response(),相当于DJango中的HttpResponse。
如果视图函数单纯返回指定字符串的话,flask会自动进行一些封装让他变成浏览器可以读取的格式,也就是content-type = text/html,状态码为200。
Flask提供的make_response 方法来自定义自己的response对象
响应html文本
app.route("/hello")
def hello():
response = make_response("<html>hello bobo!</html>")
return response
返回JSON数据
在 Flask 中可以直接使用 jsonify 生成一个 JSON 的响应
from flask import Flask, request, jsonify
# jsonify 就是json里面的jsonify
@app.route("/")
def index():
# 也可以响应json格式代码
data = [
{"id":1,"username":"liulaoshi","age":18},
{"id":2,"username":"liulaoshi","age":17},
{"id":3,"username":"liulaoshi","age":16},
{"id":4,"username":"liulaoshi","age":15},
]
return jsonify(data)
flask中返回json 数据,都是flask的jsonify方法返回就可以了.
重定向
永久重定向301
- http的状态码是301,多用于旧网址被废弃了要转到一个新的网址确保用户的访问,比如京东的网站,你输入www.jingdong.com的时候,会被重定向到www.jd.com,因为jingdong.com这个网址已经被废弃了,被改成了jd.com,所以这种情况下应该使用永久重定向
临时重定向302
- http的状态码是302,表示页面的临时性跳转。比如访问一个需要权限的网址,如果用户没有登录,应该重定向到登录页面,这种情况下,应该用临时重定向
- 在flask中,重定向是通过flask.redict(location, code=302)函数来实现的
重定向到百度页面
from flask import redirect
# 页面跳转响应
@app.route("/user")
def user():
# 页面跳转 redirect函数就是response对象的页面跳转的封装
# Location: http://www.baidu.com
return redirect("http://www.baidu.com")
重定向到自己写的无参数的视图函数
可以直接填写自己 url 路径
也可以使用 url_for 生成指定视图函数所对应的 url
from flask import url_for
# 内容响应
@app.route("/")
def index():
# [默认支持]响应html文本
# return "<img src='http://flask.pocoo.org/static/logo.png'>"
# 也可以响应json格式代码
data = [
{"id":1,"username":"liulaoshi","age":18},
{"id":2,"username":"liulaoshi","age":17},
{"id":3,"username":"liulaoshi","age":16},
{"id":4,"username":"liulaoshi","age":15},
]
return jsonify(data)
#使用url_for可以实现视图方法之间的内部跳转
# url_for("视图方法名")
@app.route("/login")
def login():
return redirect( url_for("index") )
重定向到带有参数的视图函数
在 url_for 函数中传入参数
# 路由传递参数
@app.route('/user/<user_id>')
def user(user_id):
return 'hello %d' % user_id
# 重定向
@app.route('/demo4')
def demo4():
# 使用 url_for 生成指定视图函数所对应的 url
return redirect(url_for(endpoint="user",user_id=100) )
自定义状态码和响应头
在 Flask 中,可以很方便的返回自定义状态码,以实现不符合 http 协议的状态码,例如:status code: 666
@app.route('/demo4')
def demo4():
return '状态码为 666', 400
"""还可以使用make_response创建Response对象,然后通过responsse对象返回数据"""
from flask import make_response
@app.route("/rep")
def index7():
response = make_response("ok")
print(response)
response.headers["Company"] = "oldboy" # 自定义响应头
response.status_code = 201 # 自定义响应状态码
return response
在页面中返回图片字节数据
@app.route('/img')
def img():
with open('./bobo.jpg','rb') as fp:
img_data = fp.read()
response = make_response(img_data)
response.headers['Content-Type'] = 'application/zip'
return response
send_files
@app.route('/img')
def img():
return send_file('1.jpg')
本文来自博客园,作者:长情不羁的五年,转载请注明原文链接:https://www.cnblogs.com/grlend/articles/14395617.html

浙公网安备 33010602011771号