flask知识点

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 :从服务器删除资源。
五、服务器返回的数据格式,应该尽量使用JSON,避免使用XML。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,174评论 22 257
  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    aimaile阅读 26,458评论 6 428
  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    小迈克阅读 2,972评论 1 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 好像每天的5分钟都要等到分开回寝室的时候才发给你,嘿嘿嘿。没有其他原因,就是你在身边的时候能说的想到的我马上就说了...
    握着荆条阅读 158评论 0 0