flask:
新建项目使用:
- 新建Flask项目
- 导入Flask类
from flask import Flask
- Flask函数接收一个参数name,它会指向程序所在的模块
app = Flask(__name__)
- 装饰器的作用是将路由映射到视图函数index
@app.route('/')
def index():
return 'Hello World'
- Flask应用程序实例的run方法启动WEB服务器
if __name__ == '__main__':
app.run()
初始化参数
- import_name: 模块名
- static_url_path: 静态文件访问前缀
- static_folder: 默认‘static’
- template_folder: 默认‘templates’
配置参数
- app.config.from_pyfile(“yourconfig.cfg”)
- app.config.from_object()
读取配置参数
- app.config.get()
- 在视图中 current_app.config.get()
app.run的参数
- app.run(host=”0.0.0.0”, port=5000, debug = True)
请求方式限定
使用 methods 参数指定可接受的请求方式,可以是多种
@app.route('/',methods=['GET', 'POST'])
def hello():
return 'hello world'
路由查找方式
同一路由指向两个不同的函数,在匹配过程中,至上而下依次匹配(查找到就不在匹配)
@app.route('/')
def hello():
return 'hello world'
@app.route('/')
def hello_flask():
return 'hello flask'
所以上面路由 /
输出的结果为 hello 函数的结果
给路由传参示例
- 大致原理是将参数强转为int, 如果成功, 则可以进行路由匹配
- 如果参数无法转换成功, 就无法匹配该路由
@app.route('/orders/<int:order_id>')
def hello_world(order_id):
print type(order_id) # 类型为int
return 'hello world %d' % order_id
重定向redirect示例
方式一: 使用redirect
from flask import redirect
@app.route('/redirect')
def redirect_demo():
return redirect('http://www.baidu.com')
方式二:使用redirect和url_for
from flask import url_for
@app.route('/redirect')
def redirect_demo():
# url_for: 根据传入的视图函数名, 找到对应的路由地址
# 两者通常结合使用
print url_for('index')
return redirect(url_for('index'))
返回JSON
方式一: 使用json.dumps()
- 仅仅是将字典转换为JSON格式的字符串.
- 返回的响应头Content-Type为text/html
from flask import Flask,json
@app.route('/json')
def do_json():
hello = {"name":"stranger", "say":"hello"}
return json.dumps(hello)
# 如果要实现和方式二一样的效果, 可以使用如下方式
# return 第一个参数: 返回的数据, 第二个参数: 状态码, 第三个参数: 设置响应头信息
# return json.dumps(json_info), 200, {'Content-Type': 'application/json'}
方式二: 使用jsonify()
- 除了将字典转换为JSON格式的字符串
- 同时会设置响应头Content-Type为application/json
- 建议使用jsonify, 前后端分离的项目中, 前后端都通过JSON进行数据交流
from flask import Flask,json
@app.route('/json')
def do_json():
hello = {"name":"stranger", "say":"hello"}
return jsonify(hello)
返回状态码示例
在 Python 中返回状态码有两种方式实现:
- 直接return
- 可以自定义返回状态码,可以实现不符合http协议的状态码,例如:error=666,errmsg='查询数据库异常',其作用是为了实现前后端数据交互的方便
- abort方法
- 只会抛出符合http协议的异常状态码,用于手动抛出异常
- 具体讲解详见<异常捕获>一节
@app.route('/')
def hello_world():
return 'hello world',666
正则路由示例
在web开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,限制访问,优化访问. 这一点Flask没有Django方便, 在实际开发中, 通常都需要自己定义一个正则路由转换器
- 导入转换器包
from werkzeug.routing import BaseConverter
- 自定义转换器并实现
class Regex_url(BaseConverter):
def __init__(self,url_map,*args):
super(Regex_url,self).__init__(url_map)
self.regex = args[0]
- 将自定义转换器类添加到转换器字典中
app.url_map.converters['re'] = Regex_url
- 使用re转换器并传入正则表达式来实现路由的匹配
@app.route('/user/<re("[a-z]{3}"):id>')
def hello_world(id):
return 'hello %s' %id
自带几种转换器
系统实际提供了6个转换器可供开发者使用. 当使用<>来接收参数时, 就会调用系统默认的转换器进行匹配工作.
- 默认的就是UnicodeConverter, 所以不填转换器名称, 或者使用default、string都是一样的.
- 默认将参数当做普通字符串对待.
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
获取请求中的数据
flask中代表当前请求的是request对象:
常用的属性如下:
属性 | 说明 | 类型 |
---|---|---|
method | 记录请求使用的HTTP方法 | GET/POST |
headers | 记录请求中的报文头 | EnvironHeaders |
url | 记录请求的URL地址 | string |
cookies | 记录请求中的cookie信息 | Dict |
args | 记录请求中的查询参数 | MultiDict |
form | 记录请求中的表单数据 | MultiDict |
data | 记录请求的数据,并转换为字符串 | * |
files | 记录请求上传的文件 | * |
abort 方法
抛出一个给定状态代码的 HTTPException,例如想要用一个页面未找到异常来终止请求,你可以调用 abort(404)。
参数: code – HTTP的错误状态码
abort(404)
只能抛出HTTP协议的状态码
errorhandler 装饰器
注册一个错误处理程序,当程序抛出指定错误状态码的时候,就会调用该装饰器所装饰的方法
参数:code_or_exception – HTTP的错误状态码或指定异常
- 例如统一处理状态码为500的错误给用户友好的提示:
@app.errorhandler(404)
def internal_server_error(e):
return '网页找不到了', 404
请求钩子
在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:在请求开始时,建立数据库连接;在请求结束时,指定数据的交互格式。为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
请求钩子是通过装饰器的形式实现,类似于Django的中间件. Flask支持如下四种请求钩子:
- before_first_request:在处理第一个请求前运行。
- before_request:在每次请求前运行。
- after_request:如果没有未处理的异常抛出,在每次请求后运行。
- teardown_request:在每次请求后运行,即使有未处理的异常抛出。
@app.route('/')
def hello_world():
print '这里正在执行处理逻辑'
return 'Hello World!'
# 在处理第一个请求前运行. 应用场景: 比如连接数据库操作
@app.before_first_request
def before_first_request():
print 'before_first_request'
# 在每次请求前运行。应用场景: 比如对数据做效验. 如果数据有问题, 可以直接返回. 就不会再去执行对应的视图函数
@app.before_request
def before_request():
print 'before_request'
# return 'hehe'
# 如果没有未处理的异常抛出, 在每次请求后运行。应用场景: 比如拼接响应头信息. 让所有json.dumps()的数据, 统一增加Content-Type为application/json
@app.after_request
def after_request(response):
print 'after_request'
response.headers['Content-Type'] = 'application/json'
return response
# 在每次请求最后运行,即使有未处理的异常抛出。 可以捕获到异常信息
@app.teardown_request
def teardown_request(e):
print 'teardown_request %s' % e
状态保持
- 因为http是一种无状态协议,不会保持某一次请求所产生的信息,如果想实现状态保持,在开发中解决方式有:
- cookie:数据存储在客户端,节省服务器空间,但是不安全
- session:会话,数据存储在服务器端
设置cookie
from flask imoprt Flask,make_response
@app.route('/cookie')
def set_cookie():
resp = make_response('this is to set cookie')
resp.set_cookie('username', 'hello')
return resp
获取cookie
from flask import Flask,request
#获取cookie
@app.route('/request')
def resp_cookie():
resp = request.cookies.get('username')
return resp
session数据的设置与获取
session:请求上下文对象,用于处理http请求中的一些数据内容
记得设置secret_key: app.secret_key = 'changhao' secret_key的作用:https://segmentfault.com/q/1010000007295395
from flask import Flask, session, redirect, url_for
@app.route('/set_session')
def set_session():
session['username'] = 'hello'
return redirect(url_for('get_session'))
@app.route('/get_session')
def get_session():
return session.get('username')
Flask的session存放位置
flask和之前用过的其他框架有一点不同的是,它的session默认是完全保留在客户端浏览器中的,也就是说往flask的session中写入数据,最终这些数据将会以json字符串的形式,经过base64编码写入到用户浏览器的cookie里,也就是说无须依赖第三方数据库保存session数据,也无需依赖文件来保存
注意:在实际的开发过程中还是需要把session存放在redis中,通过flask-session扩展实现。
命令行启动服务器
通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式启动。
from flask import Flask
from flask_script import Manager
app = Flask(__name__)
# 把 Manager 类和应用程序实例进行关联
manager = Manager(app)
@app.route('/')
def index():
return '床前明月光'
if __name__ == "__main__":
manager.run()
script的命令行参数
传入参数而不仅仅通过app.run()方法中传参,比如我们可以通过:
python hello.py runserver -host ip地址
数据库:
安装 flask-sqlalchemy
pip install flask-sqlalchemy
如果连接的是mysql数据库,需要安装mysqldb
pip install flask-mysqldb
使用Flask-SQLAlchemy管理数据库
在Flask-SQLAlchemy中,数据库使用URL指定,而且程序使用的数据库必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。
Flask的数据库设置:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
其他设置:
# 动态追踪修改设置,如未设置只会提示警告, 不建议开启
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True
flask-数据库的基本使用:
db.session.add(role) 添加到数据库的session中
db.session.add_all([user1, user2]) 添加多个信息到session中
db.session.commit() 提交数据库的修改(包括增/删/改)
db.session.rollback() 数据库的回滚操作
db.session.delete(user) 删除数据库(需跟上commit)
数据库迁移:
#coding=utf-8
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand
from flask_script import Shell,Manager
app = Flask(__name__)
manager = Manager(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/Flask_test'
db = SQLAlchemy(app)
#第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例
migrate = Migrate(app,db)
#manager是Flask-Script的实例,这条语句在flask-Script中添加一个db命令
manager.add_command('db',MigrateCommand)
if __name__ == '__main__':
manager.run()
创建迁移仓库
#这个命令会创建migrations文件夹,所有迁移文件都放在里面。
python database.py db init
创建迁移脚本
- 自动创建迁移脚本有两个函数
- upgrade():函数把迁移中的改动应用到数据库中。
- downgrade():函数则将改动删除。
- 自动创建的迁移脚本会根据模型定义和数据库当前状态的差异,生成upgrade()和downgrade()函数的内容。
- 对比不一定完全正确,有可能会遗漏一些细节,需要进行检查
python database.py db migrate -m 'initial migration'
更新数据库
python database.py db upgrade
返回以前的版本
可以根据history命令找到版本号,然后传给downgrade命令:
python app.py db history
输出格式:<base> -> 版本号 (head), initial migration
- 回滚到指定版本
python app.py db downgrade 版本号
实际操作顺序:
- 1.python 文件 db init
- 2.python 文件 db migrate -m"版本名(注释)"
- 3.python 文件 db upgrade 然后观察表结构
- 4.根据需求修改模型
- 5.python 文件 db migrate -m"新版本名(注释)"
- 6.python 文件 db upgrade 然后观察表结构
- 7.若返回版本,则利用 python 文件 db history查看版本号
- 8.python 文件 db downgrade(upgrade) 版本号
restful
一、域名:
将api部署在专用域名下:
http://api.example.com
或者将api放在主域名下:
http://www.example.com/api/
二、版本:
将API的版本号放在url中。
http://www.example.com/app/1.0/info
http://www.example.com/app/1.2/info
三、路径:
路径表示API的具体网址。每个网址代表一种资源。 资源作为网址,网址中不能有动词只能有名词,一般名词要与数据库的表名对应。而且名词要使用复数。
示例:
#获取单个商品
http://www.example.com/app/goods/1
#获取所有商品
http://www.example.com/app/goods
四、使用标准的HTTP方法:
对于资源的具体操作类型,由HTTP动词表示。 常用的HTTP动词有四个。
GET SELECT :从服务器获取资源。
POST CREATE :在服务器新建资源。
PUT UPDATE :在服务器更新资源。
DELETE DELETE :从服务器删除资源。
网友评论