Flask本身相当于一个内核,Flask=Werkzeug+Jinja2
falsk运行过程
1.app.run() 执行了该方法后,就会将flask程序运行在一个简易web服务器(有flask提供)
2.程序实例由werkzeug实现路由分发(url请求和视图函数之间的关系)。在flask中,路由的实现一般是通过程序实例的装饰器实现。
3.flask调用视图函数后,可以返回两种内容
- 字符串内容:将视图函数的返回值作为响应内容
- html模板内容:获取到数据后,把数据传递给html模板文件,模板引擎负责渲染数据,然后返回响应数据给客户端
路由请求方式限定
@app.route('/',methods=['GET','POST']) #路由默认只支持get
路由参数处理
@app.route('/order/<int:order_id>') #int会将输入的参数强制转为正型,成功方可请求成功
def get_order_id(order_id): #要传入形参方可在内部获取
print(order_id)
应用程序配置参数
app.config 对象保存了flask的⼯程配置信息,当做字典。
- 读取
- app.config['SECRET_KEY']
- app.config.get('SECRET_KEY')
- 设置保存
- app.config['SECRET_KEY'] =xxx
批量设置 - app.config.from_object(配置对象)
- 优点,以类实现能够复用
- 缺点,将敏感配置信息暴露在代码
- app.config.from_pyfile(配置文件)
- 优点,配置信息单独维护,一定程度保证了安全
- 缺点,仍不安全,名字固定
- app.config.from_envvar('环境变量名')
- 环境变量,即由操作系统保存的变量数据
- 本质上,由环境变量保存真实配置文件的路径,flask通过这个环境变量找到配置文件再加载。
- 缺点使用麻烦
- app.config['SECRET_KEY'] =xxx
响应
模板:return render_template('index.html', my_str=xxx, my_int=xxx)
重定向:return redirect('/index')
json: return jsonify({}) ,响应体数据是json字符串,响应头Content-Type: application/json。
cookie与session
cookie
- 设置
resp = make_response()
resp.set_cookie(cookie名,cookie值) 临时cookie
resp.set_cookie(cookie名,cookie值,有效期) - 读取
request.cookies.get(cookie名) - 清除
resp=make_reponse()
resp.delete_cookie(cookie名)
session
from flask import session
需要提前设置SECRET_KEY
- 设置 session['username'] = 'python'
- 读取 session.get('username')
session数据保存到哪了?
flask 原⽣ client-side-session (session数据保存到了cookie中)
cookie session: {'username': 'python'}
异常处理
异常终止
abort()
捕获错误
@app.errorhandler(404)
@app.errorhandler(ZeroDivisionError)
请求钩子
作⽤ 中间件
- before_first_reques
- before_request
- after_request
- teardown_request
lask接收到请求之后的完整处理时序流程
接收到第⼀个请求:
-> before_first_request 提供的⽅法
-> before_request 提供的⽅法
-> 视图处理
-> after_request 提供的⽅法(视图没有发⽣异常)
-> teardown_request 提供的⽅法
-> 返回给客户端
接收以后的请求:
-> before_request 提供的⽅法
-> 视图处理
-> after_request 提供的⽅法(视图没有发⽣异常)
-> teardown_request 提供的⽅法
-> 返回给客户端
上下文
request、 session 、 current_app 、 g。在flask程序的外部,⽐如 使⽤python终端进⾏调试 或者 ⾃⼰独⽴编写脚本 ,不能直接导⼊使⽤,需要为这4个对象 创建他们的上下⽂环境。
- 创建应⽤上下⽂环境
- with app.app_context()
- 创建请求上下⽂环境
- with app.request_context({})
- 请求上下文
- request
- session
- 应用上下文
- current_app
- g
使用
- current_app
- from flask import current_app
- current_app 就是flask app ( app = Flask(name) )的代理⼈可以简单理解为 current_app 等价于app
- 应⽤场景: 在不⽅便使⽤app对象的时候,可以使⽤current_app代替
- g(g对象 g变量)
- from flask import g
- 只是flask提供的临时保存数据的"仓库", flask在每次处理⼀个请求之前都会清理g对象
- 保存的数据只对单次请求有效
- 应⽤场景:在⼀次请求涉及调⽤的多个函数间传递参数
认证机制
- 对已经签发了身份信息的用户,之后的验证处理?
- 特定视图 要求⽤户必须登录 : 装饰器
- 所有视图 要修随时可以查询⽤户的身份 如果⽤户登录 user_id=xxx 如
- 果⽤户未登录 user_id=None : 请求钩⼦ before_request
⽤户携带身份信息(session cookie jwt)发起了请求
-> 请求钩⼦ before_request 判断⽤户的身份 如果登录 g.user_id=xxx 否
则 g.user_id=None
-> 如果是不强制登录的视图 进⼊视图内部执⾏ 想要获取⽤户身份的时候
直接读取g.user_id
如果是强制登录的视图(加了装饰器) -> 装饰器中 判断g.user_id is None 返
回401 否则 进⼊视图执⾏
Jinja2
resp.delete_cookie(cookie名session
jinja2是一个模板引擎,也是用python实现的模板语言。
接口是render_template()函数
return render_template('index.html',title='Home',user=user)
需要传入的值以键值对的方式传入
变量代码块使用
{{ 变量名 }}
变量为列表时,通过点语法或者中括号方式获取子元素{{ myslit.2 }} ,{{ myslit[2] }} 获取列表中的第二个元素
变量为字典时,通过{{ mydict.key1 }} ,{{ mydict[key1] }}方式获取
控制代码块
由{% %}控制的代码块
过滤器
过滤器的本质即函数,语法如下:变量名|过滤器
{{ variable| filter_name(*args)}}
表单处理之消息闪现
flash()可传递消息给模板,模板中接收消息需要遍历
视图函数中使用:flash(u'密码不一致')
模板中使用:
{% for message in get_falshed_messages() %}
{{ message }}
其中flask()在使用之前需要设置密钥,在app初始化后加入app.secret_key = 'xxx'
数据库
使用flask-sqlalchemy拓展
- sqlalchemy是对数据库的抽象,使开发者可以不用和sql语句打交道,而是通过python对象来操作数据库。
- sqlalchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作
安装flask-sqlalchemy
- pip install flask-sqlalchemy
- 如链接mysql数据库,则还需安装mysqldb, pip install flask-mysqldb
使用flask-sqlalchemy类型管理数据库
- 在flask-sqlalchemy中,数据库通过URL指定,而且程序使用的数据库必须 保存到falsk配置对象的SQLALCHEMY_DATABASE_URI键中。
Flask的数据库设置
- app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@127.0.0.1:3306/test" (数据库连接设置,mysql为密码,test为数据库名。如未设置该选项则默认连接flask自带的sqlite)
- app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False (动态修改追踪设置,如未设置则会显示警告,不建议开启)
- app.config["SQLALCHEMY_ECHO"] = True (查询时会显示原始sql语句)
常用sqlalchemy字段类型
常用sqlalchemy列选项
选项名 | 说明 |
---|---|
primary_key | 如果为True,代表主键 |
unique | 如为True,代表不允许出现重复值 |
index | 如为True,为这列创建索引,提高查询效率 |
nullable | 如为True,允许有空值, |
default | 为这列定义默认值 |
代码示例
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('config')
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:@127.0.0.1:3306/flask_demo"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
db = SQLAlchemy(app)
class User(db.Model):
#定义表名
__tablename__ = 'users'
#定义字段
id = db.Column(db.Integer, primary_key = True)
nickname = db.Column(db.String(64), index = True, unique = True)
email = db.Column(db.String(120), index = True, unique = True)
posts = db.relationship('Post', backref='author', lazy='dynamic')
class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
def __repr__(self):
return '<Post %r>' % (self.body)
数据库基本操作
- 在flask-sqlalchemy中,插入,修改,删除操作,均由数据库会话管理。
- 数据库会话由db.session表示。在将数据写入数据库前,要先将数据添加到会话中,然后调用commit()方法提交会话。
- 在flask-sqlalchemy中,查询操作是通过query()对象操作数据
db.session.add(role) 添加数据到session中
db.session.add_all([user1,user2])
db.session.delete(user) 删除数据库(需跟上commit)
db.session.commit() 提交数据库的修改(包括增删改)
db.session.rollbask() 数据库的回滚操作
模型之间的关联
关键语句:
posts = db.relationship('Post', backref='author', lazy='dynamic')
class User(db.Model):
# 定义表名
__tablename__ = 'users'
# 定义字段
id = db.Column(db.Integer, primary_key=True)
nickname = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
#关联Post模型,方便查询。给User模型增加了一个posts属性,其中backref='author'相当于给Post模型增加了一个author属性,为反向引用
posts = db.relationship('Post', backref='author', lazy='dynamic')
def __repr__(self):
return '<User %r>' % (self.nickname)
class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
def __repr__(self):
return '<Post %r>' % (self.body)
查询操作
模型名.query.查询器 or 模型名.query.过滤器.查询器
sqlalchemy查询过滤器
过滤器 | 说明 |
---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 |
limit |
sqlalchemy查询执行器
查询执行器 | 说明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,未查询到则返回None |
first_or_404() | 返回查询的第一个结果,未查询到则返回404 |
get() | 返回指定主键对应的行,未查询到则返回None |
get_or_404() | |
count() | 返回查询结果的数量 |
1.警告内容:SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
解决方法:将config的SQLALCHEMY_TRACK_MODIFICATIONS设置为Ture或Flase即可
2.if g.user is not None and g.user.is_authenticated():用法报错
报错内容:TypeError: 'bool' object is not callable
解决方法:is_authenticated是一个属性而不是一个方法,不可加小括号