flask基本使用方法及异常场景

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通过这个环境变量找到配置文件再加载。
      - 缺点使用麻烦

响应
模板: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:

异常处理

异常终止
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] }}方式获取

控制代码块
由{% %}控制的代码块

过滤器
过滤器的本质即函数,语法如下:变量名|过滤器

表单处理之消息闪现
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是一个属性而不是一个方法,不可加小括号

posted @ 2021-03-06 16:55  tingshu  阅读(299)  评论(0编辑  收藏  举报