扩展

蓝图内置扩展 (实现的是路由的拆分)

 '''----------- app.py -------------'''
from flask import Flask
from users_views import blue1
from orders_views import blue2 app = Flask(__name__) # 路由注册
app.register_blueprint(blueprint=blue1)
app.register_blueprint(blueprint=blue2) if __name__ == '__main__':
app.run()
 ''' ------------ users_views.py ---------------'''
from flask import Blueprint
# blue1 的设置(名字,导入的名字,前缀名称)
blue1 = Blueprint("blue1",__name__, url_prefix="/users") # 用blue1设置路由,用前缀名字区分相同名字的路由:http://127.0.0.1:5000/users/
@blue1.route("/")
def index():
return "用户的 Blue 信息" @blue1.route("/user/")
def home():
return "用户信息"
 ''' ----------- orders_vieews.py ----------'''
from flask import Blueprint
# blue2 的设置(名字,导入的名字,前缀名称)
blue2 = Blueprint("blue2", __name__, url_prefix="/orders") # 用blue2设置路由,用前缀名字区分相同名字的路由:http://127.0.0.1:5000/orders/
@blue2.route("/")
def haha():
return "订单的 blue2 信息" @blue2.route("/orders/")
def ppp():
return "订单信息"

静态文件路径

 from flask import Flask
from users_views import blue1
from orders_views import blue2
# 静态文件路径配置。static_folder='news/static' 是配置新的静态文件的路径
app = Flask(__name__,static_folder='news/static') # 路由注册
app.register_blueprint(blueprint=blue1)
app.register_blueprint(blueprint=blue2)

终端命令启动项目插件扩展:

  • 实现:flask-script
  • 安装:pip install flask-script
  • 作用:实现命令键入的方式 启动项目
  • 使用:在终端键入:python app.py runserver 
    • 查看帮助文档:  python app.py runserver --help
    • 设置指定端口:  python app.py runserver -h ip地址 -p 端口号
    • 设置自动重启:  python app.py runserver -r
    • 设置调试模式:  python app.py runserver -d
    • shell脚本调试:  python app.py shell   在终端内添加model数据
  • 配置:
 from flask import Flask
from flask_script import Manager app = Flask(__name__)
# 配置flask-script
manager = Manager(app=app) @app.route('/')
def hello_world():
return 'Hello World!' # 使用flask-script
if __name__ == '__main__':
manager.run() flask-script

对象模型迁移数据库表扩展:

  • 实现:flask-migrate
  • 安装:pip install flask-migrate -i http://pypi.douban.com/simple
  • 作用:迁移,可以自动将模型转变成数据库中的表
  • 配置:
    • 在extension.py扩展文件中绑定app和db。详见下面代码块 ;创建一个Migrate对象,传递app和db进去
    • 然后,在manage.py启动文件的manager对象上添加指令:manager.add_command("db",MigrateCommand)
  • 使用:
    • 首次使用需要初始化:           python manage.py db init
    • 如果模型有变更,生成迁移文件:python manage.py db migrate
    • 将迁移文件映射到数据库中:  python manage.py db upgrade
    • 后悔返回,回滚操作:     python manage.py db downgrade
  • extension.py
 from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
# 扩展文件添加配置信息。创建一个Migrate对象。
migate = Migrate() # 应用一个函数,使用函数传参数将app导入初始化
def init_ext(app):
db.init_app(app)
migate.init_app(app,db) # 将app和db以参数的形式传递进去。注册上
  • manage.py
 # 注册迁移工具命令行
manager.add_command("db",MigrateCommand) if __name__ == '__main__':
manager.run()
  • 未拆分写法
 from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
from app import create_app, db app = create_app()
manager = Manager(app=app) # 创建迁移工具实例
migrate = Migrate()
migrate.init_app(app=app,db=db) # 注册迁移工具命令行
manager.add_command("db",MigrateCommand) if __name__ == '__main__':
manager.run()

数据库模型和对象关系扩展

  • 实现:SQLAlchemy;                 pymysql驱动
  • 安装:pip install flask-sqlalchemy ;pip install pymysql
  • 作用:ORM(Object Relational Mapping) 对象关系映射。将数据库转为面向对象的操作,通过操作对象就可实现对数据的CRUD
  • 配置:
 from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置连接sqlite数据库的指定信息。SQLite数据库连接不需要额外驱动,也不需要用户名和密码
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hello.sqlite'
# 设False为更好的兼容性,禁止对象追踪修改
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) # 配置连接mysql数据库的指定信息。dialect+driver://username:password@host:port/database
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:guoyapeng@localhost:3306/FlaskModel'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app) if __name__ == '__main__':
app.run()
  • 使用:下面链接文件中的 模型板块

https://www.cnblogs.com/TMMM/p/11450872.html


缓存技术cache扩展库插件:

  • 实现:flask_caching
  • 安装:pip install flask-caching
  • 作用:
    • 减少磁盘IO可以大幅度提升服务器性能。
    • 数据库IO操作的是web应⽤性能的瓶颈。为了提⾼访问效率,应尽可能减少数据库的操作。
    • 可以将经常访问的数据缓存起来,再次使⽤用时直接从缓存中获取,而不是每次都操作数据库。
  • 字段
from flask_caching import Cache

cache = Cache()
cache.init_app(app=app, config={'CACHE_TYPE': 'simple'})
 CACHE_REDIS_URL    # 连接到Redis服务器的URL。一键配置示例
cache = Cache(config={
"CACHE_TYPE": "redis",
"CACHE_REDIS_URL":"redis://:localhost@127.0.0.1:6379/1",}) # 以下参数是所有的类型共有的
CACHE_NO_NULL_WARNING = "warning" # null类型时的警告消息
CACHE_ARGS = [] # 在缓存类实例化过程中解包和传递的可选列表,用来配置相关后端的额外的参数
CACHE_OPTIONS = {} # 可选字典,在缓存类实例化期间传递,也是用来配置相关后端的额外的键值对参数
CACHE_DEFAULT_TIMEOUT # 默认过期/超时时间,单位为秒
CACHE_THRESHOLD # 缓存的最大条目数 CACHE_TYPE: # 设置缓存的类型
CACHE_TYPE = null # 默认的缓存类型,无缓存
CACHE_TYPE = 'simple' # 使用本地python字典进行存储,非线程安全
CACHE_TYPE = 'filesystem' # 使用文件系统来存储缓存的值
CACHE_TYPE = 'memcached' # 使用memcached服务器缓存
CACHE_TYPE = 'redis' # 使用redis作为缓存
 CACHE_TYPE = 'filesystem' # 使用文件系统来存储缓存的值
CACHE_DIR = "" # 文件目录 CACHE_TYPE = 'memcached' # 使用memcached服务器缓存
CACHE_KEY_PREFIX # 设置cache_key的前缀
CAHCE_MEMCACHED_SERVERS # 服务器地址的列表或元组
CACHE_MEMCACHED_USERNAME # 用户名
CACHE_MEMCACHED_PASSWORD # 密码 CACHE_TYPE = 'redis' # 使用redis作为缓存
CACHE_KEY_PREFIX # 设置cache_key的前缀
CACHE_REDIS_HOST # redis地址
CACHE_REDIS_PORT # redis端口
CACHE_REDIS_PASSWORD # redis密码
CACHE_REDIS_DB # 使用哪个数据库
  • 配置
  • manage.py
from flask_script import Manager
from app import create_app app = create_app()
manager = Manager(app=app) if __name__ == '__main__':
manager.run()
  • app/__init__.py
from flask import Flask
from app import views, ext def create_app():
app = Flask(__name__)
# 注册缓存配置
ext.init_cache(app)
# 注册路由
app.register_blueprint(views.bp)
return app
  • app/ext.py
 from flask_caching import Cache

 cache = Cache()

 def init_cache(app):

     # CACHE_TYPE = 'redis'    使用redis作为缓存
# CACHE_KEY_PREFIX 设置cache_key的前缀。不设置表示默认
# CACHE_REDIS_HOST redis地址
# CACHE_REDIS_PORT redis端口
# CACHE_REDIS_PASSWORD redis密码。没密码就不用设置
# CACHE_REDIS_DB 使用哪个数据库,不设置表示随机 app.config["CACHE_TYPE"] = "redis"
app.config["CACHE_REDIS_HOST"] = "127.0.0.1"
app.config["CACHE_REDIS_PORT"] = 6379
# 设置缓存到app上
cache.init_app(app=app)
  • 使用
  • movies/views.py
 from time import sleep
from app.ext import cache @user_blue.route("/learn/")
@cache.cached(60) # 设置缓存,60秒有效
def learn():
print("开始学习")
sleep(10)
print("结束学习")
return "缓存技术,提高学习时间"

会话技术session扩展库插件

  • 实现:flask_session
  • 作用:实现http的长链接,用会话技术为了数据可以跨请求使用,让服务器识别客户端
  • 安装:pip install flask-session
  • 配置:
 import datetime
from flask import Flask
from flask_session import Session
from app import views def create_app(): app = Flask(__name__) # 为sesson设置一个密钥key值。两种方式,推荐第二种
# app.secret_key = 'asdfghjkl'
app.config['SECRET_KEY'] = 'd53a40dae292df9d409ef64e4a04905d' # flssk-session 扩展配置
# 指定 flask-session 扩展将 session 数据持久化到 redis 中
app.config['SESSION_TYPE'] = 'redis' # 指定 flask-session 存储在 redis 中的 session id的前缀
app.config['SESSION_KEY_PREFIX'] = 'flask:session' # 自定义 session 过期时间
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=7) # 创建 flask-session 的 Session 对象
sess = Session() # 将 flask-session 扩展初始化,跟app建立链接
sess.init_app(app=app) app.register_blueprint(views.bp) # 注册路由
return app
  • 使用: 以下链接中的 session会话 模块

https://www.cnblogs.com/TMMM/p/11478808.html


管理⽤户登录登出扩展库插件:

  • 实现:flask-login
  • 安装:pip install flask-login
  • 作用:是一个专门用来管理用户登录退出的扩展库
  • 步骤:
    • 1.  在extension.py中 app上注册flask-login扩展,指定登陆页面。如下两行代码
    • 2. 在model.py中 在登陆对象(User)中继承 UserMixin类,提供便捷的功能
    • 3. 在views.py中 增加load_user回调函数,导入扩展文件包加装饰器@login_manager.user_loader。
    •     供flask-login扩展在内部加载当前登陆的用户对象。flask-login默认通过user id的方式,调用load_user函数,获得用户对象
    • 4. 登陆成功后,调用login_user(user)将登陆成功的对象绑定到session中
    • 5. 使用lagin_required装饰器,保护访问受限的视图函数
  • 配置:
    • manage.py 注册
 # 添加扩展
from flask import Flask
from flask.ext.login import LoginManager app = Flask(__name__) # 1.实例化login_manager
login_manager = LoginManager()
# 2.将login_manager与app绑定
login_manager.init_app(app)
# 3.设置登录视图名称。如果未登录用户请求只有登录用户才能访问的视图,则重定向到这个设置的登录视图。
login_manager.login_view = 'blue.login' # 4.如果未设置登录视图,则直接返回401错误。设置登录错误信息
login_manager.login_message = '请登录!'
    • models.py 继承
 from flask_login import UserMixin
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
# 让User继承自UserMixin。
class User(UserMixin,db.Model):
__tablename__= "users"
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(16),unique=True,nullable=False)
password = db.Column(db.String(256),unique=True,nullable=False)
    • views.py 初始化
 # 告诉ext.py中login_manager的用户是从哪来的。用户加载的地方
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
  • 使用
 """
状态切换:
  login_user # 登录
4   logout_user # 退出登录 路由保护:
7   login_required # 保护需要登录才能访问的路路由 当前用户:
10   current_user # 哪⾥都可以使⽤(在模板中不需要分配) 实现回调:
13   @login_manager.user_loader
14   def load_user(uid):
15    return User.query.get(uid)
"""
 #属性 is_authenticated
#当用户登录成功后,该属性为True。 #属性 is_active
#如果该用户账号已被激活,且该用户已登录成功,则此属性为True。 #属性 is_anonymous
#是否为匿名用户(未登录用户)。 #方法 get_id()
#每个用户都必须有一个唯一的标识符作为ID,该方法可以返回当前用户的ID,这里ID必须是Unicode。
 <body>

 9 {# 当前用户:current_user,属性:is_authenticated 当前用户登录成功后该属性为True。 #}
10 {# 判断用户是否登陆,如果登陆显示:用户名、注销、用户主页、关于网站。如果没有登陆显示:请登录、用户主页、关于网站 #}
{% if current_user.is_authenticated %}
当前登陆用户为:{{ current_user.username }}<a href="{{ url_for("blue.logout") }}">注销</a>
{% else %}
<a href="{{ url_for("blue.login") }}">请登录</a>
{% endif %}
<a href="{{ url_for("blue.home") }}">用户主页</a>
<a href="{{ url_for("blue.about") }}">关于网站</a> </body>
    • models.py
 from flask_login import UserMixin
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class User(UserMixin,db.Model):
__tablename__= "users"
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(16),unique=True,nullable=False)
password = db.Column(db.String(256),unique=True,nullable=False)
    • views.py
 from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required
from werkzeug.security import generate_password_hash, check_password_hash
from app.ext import login_manager
from app.models import User, db bp = Blueprint('blue', __name__) @bp.route('/register/', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
# 处理注册逻辑。 1、检查两次输入的密码是否相等; 2、检查用户名是否重复
username = request.form.get('username')
password = request.form.get('password')
re_password = request.form.get('re_password') # 检查两次输入的密码是否相等
if password != re_password:
return render_template('register.html', msg='两次输入密码不一致', username=username)
# 查询数据库中是否有重复的用户名。 .count() 获得查询语句匹配到的行数
if User.query.filter_by(username=username).count() > 0:
return render_template('register.html', msg='用户名重复', username=username) # 对 password 进行加密。进行存储准备
password_hash = generate_password_hash(password)
user = User()
user.username = username
user.password = password_hash
# 对新注册的用户进行存储
db.session.add(user)
db.session.commit() # flash 闪现消息,可以跨请求传递消息,不跨请求时也可以使用
# 本质上:内部会把消息保存到 session中,在下一个请求中通过session获取
"""
在 html 中使用
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
"""
flash('注册成功,请登录')
return redirect(url_for('blue.login'))
return render_template('register.html') @bp.route("/login/",methods=["POST","GET"])
def login():
if request.method == "POST":
# 处理登陆业务
username = request.form.get("username")
password = request.form.get("password") user = User.query.filter_by(username=username).first()
if user is None:
return render_template("login.html",msg="用户或密码错误",username=username)
if check_password_hash(user.password,password): # 登陆成功以后需要将登陆状态保存到session中session['uid']=user.id,使用flask-login的login_user()来完成
login_user(user) # 即使是post请求,也可以用args获取跳转链接next的参数值,http://127.0.0.1:5000/login/?next=%2Fhome%2F
next_url = request.args.get("next")
# 如果存在 next 跳转参数,则跳转到 next 页面;否则调转到首页
return redirect(next_url or url_for("blue.index"))
else:
return render_template("login.html", msg="用户或密码错误", username=username)
return render_template("login.html") # 保护页面。需要配置默认调转页面
# 使用装饰器:@login_required 实现:只有登陆的用户,点击home时页面才会看到信息;没有登陆的用户点击会被跳转到登陆页面
@bp.route("/home/")
@login_required
def home():
return "home" # 登出操作。用 flask-login的logout_user()自动完成登出时session的清理工作
@bp.route("/logout/")
def logout():
logout_user()
return redirect(url_for("blue.index")) # 告诉ext.py中login_manager的用户是从哪来的。用户加载的地方
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id) @bp.route("/about/")
def about():
return "about" @bp.route('/')
def index():
return render_template('index.html')

views.py


表单验证模块扩展库插件:

  • 实现:flask-wtf
  • 作用:是flask框架的表单验证模块。可以很方便生成表单、验证表单的数据。CSRF、字段校验等功能。
  • 安装:pip install flask-wtf
  • 注意:如果使用form提交的话,自动将form.py中的属性和html中的同名元素匹配,html中需要注明 {{ form.csrf_token }}
    • form.py中的 username = StringField(...)匹配 .html中的  <input name="username">

  • 字段

     

  SelectField:下拉框内容在 form 表单类初始化时即确定。运行中修改不生效(验证时会出错)

  QuerySelectField:下拉框内容可以动态从数据库中获取,query_factory指定查询接口

  • 配置:

    • form.py
 from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Length, EqualTo class RegisterForm(FlaskForm):
# 定义页面中显示的字段标签。username是StringField类型
username = StringField(
# label标签 显示:"用户名"
label='用户名',
# 验证器:列表类型。
validators=[
# DataRequired 必填信息
DataRequired(message='用户名为必填')
]
)
password = PasswordField(
label='密码',
validators=[
DataRequired(message='密码为必填'),
# 长度验证(最小2,最长4)
Length(min=2, max=4, message='密码长度为 2 ~ 4'),
]
)
password_confirm = PasswordField(
label='重复密码',
validators=[
# EqualTo验证和谁相等(要比较的变量)
EqualTo('password', message='两次输入的密码必须一致'),
]
) class LoginForm(FlaskForm):
username = StringField(
label='用户名',
# 默认值:空
default='',
validators=[
DataRequired(message='用户名为必填')
]
)
password = PasswordField(
label='密码',
validators=[
DataRequired(message='密码为必填'),
]
)
  • 使用:
    • views.py
 from flask import Blueprint, render_template, request, redirect, url_for
from flask_login import login_user
from werkzeug.security import generate_password_hash, check_password_hash
from app.ext import login_manager
from app.form import RegisterForm, LoginForm
from app.models import User, db bp = Blueprint('blue', __name__) @bp.route('/form/register/', methods=['GET', 'POST'])
def register_form():
form = RegisterForm()
# 普通写法:
# if request.method == 'POST':
# username = request.form.get('username') # form写法
# validate_on_submit 内部做了三件事
# 1、判断 request.method 是否为 POST, PUT, PATCH, DELETE
# 相当于 if request.method == 'POST'
# 2、将表单中的同名元素自动绑定到form中的同名属性中
# 相当于 username = request.form.get('username')
# form.username = username
# 3、验证表单数据,根据表单字段中定一个的 validators
if form.validate_on_submit():
# 前端数据在form验证通过后,从form获取前端传入的数据
print(form.data)
username = form.username.data
password = form.password.data password_hash = generate_password_hash(password) user = User()
user.username = username
user.password = password_hash db.session.add(user)
db.session.commit()
return redirect(url_for('blue.login_form'))
return render_template('register_form.html', form=form) # 返回form对象数据 @bp.route('/form/login/', methods=['POST', 'GET'])
def login_form():
form = LoginForm() # validate_on_submit 内部做了三件事
# 1、判断 request.method是否为POST, PUT, PATCH, DELETE
# 相当于 if request.method=='POST'
# 2、将表单中的同名元素自动绑定到form中的同名属性中
# 相当于 username = request.form.get('username')
# form.username = username
# 3、验证表单数据,根据表单字段中定一个的 validators
if form.validate_on_submit():
username = form.username.data
password = form.password.data # 先根据用户名查询数据库中是否有该数据
user = User.query.filter_by(username=username).first() if user is None:
# 如果查询的对象不存在。手工向form.username.errors追加一条错误信息,通过form显示到前端页面
form.username.errors.append('用户或密码错误')
return render_template('login_form.html', form=form) if check_password_hash(user.password, password):
# 如果密码验证通过。使用flask-login的login_user()完成保存登陆状态的工作
# 登录成功以后,需要将登录状态保存到session中,比如:session['uid']=user.id
login_user(user) # 获得跳转连接,如果url中存在next跳转参数,则跳转到next页面,否则跳转到首页
# 通过args获取post请求中的URL的next参数信息
next_url = request.args.get('next')
return redirect(next_url or url_for('blue.index'))
else:
form.password.errors.append('用户或密码错误')
return render_template('login_form.html', form=form)
return render_template('login_form.html', form=form) @bp.route("/form/index/",methods=['POST','GET'])
def index():
return render_template("index.html") @login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
 # 修改资源
@app.route('/article/<article_id>/change/', methods=['POST', 'GET'])
def article_change(article_id):
article = Article.query.get(article_id)
# 根据 数据库中查询到的数据 创建 Form 对象
# ArticleForm 内部会 将 article 对象的同名属性设置到 ArticleForm 的同名属性上
# form.title = article.title
# form.content = article.content
# form.title.data
form = ArticleForm(obj=article)
if form.validate_on_submit():
# 使用表单对象的 populate_obj 方法,用已验证表单的内容来填充 Article 对象
# 将表单中提交过来的内容,再次反向绑定form上去
# article.title = form.title.data
# article.content = form.content.data
form.populate_obj(article)
db.session.commit() flash('文章保存成功')
return redirect(url_for('blue.article_list'))
return render_template('article-change.html', form=form)

修改资源

    • login_form.html
 <body>
<form action="{{ url_for("blue.index") }}" method="post">
{# <跨域访问></防跨域访问> #}
{{ form.csrf_token }}
                         {# 登陆验证失败后: <重新显示输入的信息> </返回错误原因> #}
用户名:<input name="username" type="text" value="{{ form.username.data }}">{{ form.username.errors }}
密码:<input name="password" type="password" value="">{{ form.password.errors }}
<input type="submit" value="submit">
</form>
</body>
    • register.html
 <body>
<form action="" method="post">
{# <csrf防跨域访问></csrf防跨域访问> #}
{{ form.csrf_token }}
{# flask-wtf 写法 #}
{{ form.username.label }} {{ form.username() }} {{ form.username.errors }}
{{ form.password.label }} {{ form.password }} {{ form.password.errors }}
{{ form.password_confirm.label }} {{ form.password_confirm }} {{ form.password_confirm.errors }}
<input type="submit" value="submit">
</form>
</body>

缓存技术

方法

"""
cache.cached:装饰器,装饰无参数函数,使得该函数结果可以缓存
参数:
timeout: 超时时间
key_prefix: 设置该函数的标志
unless: 设置是否启用缓存,如果为True,不启用缓存
forced_update: 设置缓存是否实时更新,如果为True,无论是否过期都将更新缓存
query_string: 为True时,缓存键是先将参数排序然后哈希的结果 cache.memoize:装饰器,装饰有参数函数,使得该函数结果可以缓存
参数:
make_name:设置函数的标志,如果没有就使用装饰的函数
其他参数同cached cache.delete_memoized:删除缓存
参数:
func_name:缓存函数的引用
*args:函数参数
"""
# cache.clear()  # 清除缓存所有的缓存,这个操作需要慎重
# cache.get(key) # 获取一个键的值,如果值是json格式会自动转化成字典
# cache.set(key,value,timeout)     #设置一个键值,value可以是字典,会自动转化json格式的字符串
# cache.add(key, value, timeout=None) #设置一个键值,如果存在就pass,注意和set的区别
# cache.delete(key) #删除键

流程

  

使用 

  • app/views.py
 import random
import time
from flask import Blueprint
from app.ext import cache bp = Blueprint("blue",__name__) # 缓存视图函数 设置缓存。过期时间10秒
@bp.route("/cache_views/")
@cache.cached(timeout=10)
def cache_views():
"""
当通过 cache.cached 缓存视图函数时,
在超时之前(timeout<10)访问此视图函数,会先去去缓存中查找,返回缓存中的数据。
在超时之后(timeout>10)访问此视图函数,会去缓存中查找,查不到再去数据库中查找,后保存在缓存中并返回数据。
:return: 例如:网站首页,不经常变化的话,可以将其存到缓存中
"""
now = time.time()
return str(now) # 缓存普通函数(单独缓存某个函数,提供更好的复用性)
# 推荐指定key_prefix,缓存key的前缀。否则key为调⽤的视图函数所在的路由
@cache.cached(timeout=30, key_prefix='random_list')
def random_list(): # 随机提取十个数字
return [random.randint(0, 100) for _ in range(10)] @bp.route('/random_view/')
def random_view():
list0 = random_list() # 获取缓存中的十个数据
list1 = ",".join(map(str,list0))
list2 = list1 + "------>" + str(random.randint(0, 100))
return list2 # 缓存带参函数
@cache.memoize(timeout=30,make_name="random_parm")
def random_parm(arg1, arg2):
return arg1 + arg2 + random.randint(0,10)
# 根据参数值 随机获取数值。参数不同 获得的随机数不同,且互不影响
# http://127.0.0.1:5000/random_args/1/3/ 结果:4----->73
# http://127.0.0.1:5000/random_args/1/2/ 结果:6----->48
@bp.route("/random_args/<int:arg1>/<int:arg2>/")
def random_args(arg1,arg2):
return str(random_parm(arg1,arg2)) + "----->" + str(random.randint(0,100))
# 清理缓存。cache.delete(函数名,此函数参数,此函数参数)
@bp.route("/delete/<int:arg1>/<int:arg2>")
def delete(arg1,arg2):
cache.delete(random_parm,arg1,arg2)
return "ok" # 缓存对象(键值对)。cache.set('键', '值', 过期时间)
@bp.route("/set_cache/")
def set_cache():
cache.set('name', '老王', timeout=30)
cache.set('persion', {'name': '晓黎', 'age': 18}, timeout=30)
cache.set('lst', [1, 2, 3, 4], timeout=30)
# 模拟登录成功后,把用户身份信息保存到 session
session_id = ''
cache.set(session_id, {'user_id': 123456}, timeout=1800) print(cache.get('name'))
print(cache.get('persion'))
print(cache.get('lst'))
# 模拟 根据 session_id 获取用户的身份信息
print(cache.get(session_id)) return "ok"

会话技术(cookie)

 出现原因:HTTP是无状态协议,使用的短连接,请求周期非常短。使用会话技术为了数据可以跨请求使用,让服务器识别客户端

 Cookie:Cookie客户端会话技术,数据都存储在浏览器中,默认携带本网站的所有Cookie。缺点:明文传输不安全

      Cookie以key-value存储,支持过期,默认关闭浏览器即失效;不能跨浏览器,不能跨域名访问

 

  • manage.py
 from flask_script import Manager
from app import create_app app = create_app()
manager = Manager(app=app) if __name__ == '__main__':
manager.run()
  • app/__init__.py
 from flask import Flask
from app import views def create_app():
app = Flask(__name__) # 实例化 Flask对象
app.register_blueprint(views.bp) # 将蓝图注册到app上
return app # 返回出去 Flask实例
  • app/views.py
 from flask import Blueprint, request, render_template, make_response, redirect, url_for, abort

 # 用蓝图管理路由,规划url。参数("蓝图名字",__name__)
# 蓝图必须了管理的视图在一个文件中,不然不能使用
bp = Blueprint("blue",__name__) @bp.route('/index')
def index():
username = request.cookies.get('username','游客')
return render_template("index.html",username= username) @bp.route('/login/',methods=['GET','POST'])
def login():
if request.method == "POST":
username = request.form.get('username')
# 模拟登陆。使用redirect 来获取响应对象。
response = redirect(url_for('blue.index'))
# 通过response对象设置cookie
response.set_cookie('username',username)
return response
# render_template(模版名称,**context) **context是需要传递到模版中的 变量
return render_template('login.html') @bp.route('/logout/')
def logout():
# 模拟登陆,使用redirect 来获取响应对象。
response = redirect(url_for('blue.index'))
# 删除cookie
response.delete_cookie('username')
return response
  • app/templates/index.html
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h2>欢迎:{{ username }}</h2>
<form action="{{ url_for('blue.logout')}}" method="get">
<input type="submit" value="登出">
</form>
</body>
</html>
  • app/templates/login.html
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{{ url_for('blue.login')}}" method="post">
<input type="text" name="username" value="" placeholder="请输入用户名">
<input type="submit" value="登录">
</form>
</body>
</html>

会话技术(session)

 Session:服务端会话技术,数据都存储在服务端

  1、当浏览器第一次访问 web 服务器时,web 服务器会为此浏览器生成一个 session,为这个 session 创建一个唯一的 session_id;

  2、在服务器返回请求时,会向浏览器设置 cookies,cookies 中是 key-value 存储reseponse.set_cookies('session_id', session_id, expire=)

  3、浏览器再次访问此 web 服务器时,会在请求中带上 cookies 信息,即:session_id: dsfksdlfj232wrwdsf

  4、当 web 服务器在次接收到浏览器请求时,会从请求的 cookies 中提取 session_id 的值,

     然后根据 session_id 的值,查找到与当前浏览器匹配的 session(比如:从数据库查询等)

 绘画特性:依赖于Cookie,以key-value存储、相对安全、不能跨网站,不能跨域名、支持过期默认31天 -> 设置:session.permanent = True

   

  • manage.py
from flask_script import Manager
from app import create_app app = create_app()
manager = Manager(app=app) if __name__ == '__main__':
manager.run()
  • app/__init__.py
import datetime
from flask import Flask
from flask_session import Session
from app import views def create_app(): app = Flask(__name__) # 为sesson设置一个密钥key值。两种方式,推荐第二种
# app.secret_key = 'asdfghjkl'
app.config['SECRET_KEY'] = 'd53a40dae292df9d409ef64e4a04905d' # flssk-session 扩展配置
# 指定 flask-session 扩展将 session 数据持久化到 redis 中
app.config['SESSION_TYPE'] = 'redis' # 指定 flask-session 存储在 redis 中的 session id的前缀
app.config['SESSION_KEY_PREFIX'] = 'flask:session' # 自定义 session 过期时间
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=7) # 创建 flask-session 的 Session 对象
sess = Session() # 将 flask-session 扩展初始化,跟app建立链接
sess.init_app(app=app) app.register_blueprint(views.bp) # 注册路由
return app
  • app/views.py
from flask import Blueprint, render_template, redirect, url_for, request, session

# Blueprint: 第一个参数为蓝图自定义名称,第二个参数是 Blueprint 对views.py 导入时需要的名称。
bp = Blueprint('blue',__name__)
"""
在 flask 项目中使用 session
1. 为 flask 对象(app)设置secrt key
2、在任何视图函数中都可以像使用字典一样操作 session
session['username'] = 'jack' 向session中增加一个 键值对
session.get('username') 从session中根据key获取value
session.pop('username') 从session中删除指定的key
"""
@bp.route('/index/')
def index():
# session.get 从 session 中根据key获取对用的值。可以像字典一样操作
username = session.get('username','游客')
return render_template('index.html',username=username) @bp.route('/login/',methods=["POST","GET"])
def login():
if request.method == 'POST':
username = request.form.get('username')
session['username'] = username
return redirect(url_for('blue.index'))
return render_template('login.html') @bp.route('/logout/')
def logout():
session.pop('username')
return redirect(url_for('blue.index'))
 # 设置退出,
@app.route('/logout/')
def logout():
response = Response('退出成功')
response.delete_cookie('session') # 删除session中的session参数
session.pop['username'] # 删除session中的username参数值 推荐
del session['username'] # 删除session中的username参数值 不存在,会报错
return response
  • app/templates/login.html
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{{ url_for('blue.login')}}" method="post">
<input type="text" name="username" value="" placeholder="请输入用户名">
<input type="submit" value="登录">
</form>
</body>
</html>
  • app/templates/index.html
 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>欢迎:{{ username }}</h2>
<form action="{{ url_for('blue.logout')}}" method="get">
<input type="submit" value="登出">
</form>
</body>
</html>

flask 之(四) --- 扩展|缓存|会话的更多相关文章

  1. Python flask 构建可扩展的restful apl✍✍✍

    Python flask 构建可扩展的restful apl  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课 ...

  2. hiho一下 第九十五周 数论四·扩展欧几里德

    题目 : 数论四·扩展欧几里德 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho周末在公园溜达.公园有一堆围成环形的石板,小Hi和小Ho分别站在不同的石板上 ...

  3. Flask 的 请求扩展 与 中间件

    Flask 的 请求扩展 与 中间件 flask 可以通过 扩展(装饰器)来实现类似于django 中间件的功能 类似于django 的中间件, 在执行视图函数之前, 之后的执行某些功能 1 @app ...

  4. Python flask 构建可扩展的restful apl☝☝☝

    Python flask 构建可扩展的restful apl☝☝☝ Flask-RESTful是flask的扩展,增加了对快速构建REST API的支持.Flask-RESTful通过最少的设置鼓励最 ...

  5. Redis缓存篇(四)缓存异常

    这一节,我们来学习一下缓存异常.缓存异常有四种类型,分别是缓存和数据库的数据不一致.缓存雪崩.缓存击穿和缓存穿透. 下面通过了解这四种缓存异常的原理和应对方法. 缓存和数据库的数据不一致 缓存和数据库 ...

  6. Flask 扩展 用户会话

    pip install flask-login 接下来创建扩展对象实例: from flask import Flask from flask_login import LoginManager ap ...

  7. Flask 扩展 缓存

    如果同一个请求会被多次调用,每次调用都会消耗很多资源,并且每次返回的内容都相同,就该使用缓存了 自定义缓存装饰器 在使用Flask-Cache扩展实现缓存功能之前,我们先来自己写个视图缓存装饰器,方便 ...

  8. 聊聊从web session的共享到可扩展缓存设计

    先从web session的共享说起   许多系统需要提供7*24小时服务,这类系统肯定需要考虑灾备问题,单台服务器如果宕机可能无法立马恢复使用,这必定影响到服务.这个问题对于系统规模来说,从小到大可 ...

  9. flask 利用flask_wtf扩展 创建web表单

    在Flask中,为了处理web表单,我们一般使用Flask-WTF扩展,它封装了WTForms,并且它有验证表单数据的功能 创建语句格式: startTime = DateTimeField('计划开 ...

随机推荐

  1. ogg12c 配置

    环境:source 192.168.2.182 : 系统:Windows Server 2012 oracle: Release 12.1.0.2.0 ogg: 12.2.0.2.3 target 1 ...

  2. target runtime com.genuitec.runtime.genuitec.jee60 is not defined

    选中项目,右键 -> Properties -> Project Facets -> 在Runtimes 里 选择用Tomcat运行,然后 Apply -> OK. 问题解决.

  3. 我遇到的Echarts 最大值不显示&平均值不正常

    用Echarts做图表的时候,遇到最大值不显示和平均值不正常的问题,如图: 找了半天,原来是X轴6个坐标有7个数据,只是最后那个数据没有显示出来,而且还是最大的,无语. 加上第七个坐标之后,就显示正常 ...

  4. 【Share Code | HTML & CSS & Javascript】动画片段幻灯片

    [查看demo & 下载资源](https://zhaoshuquan.com/posts/15 介绍 本文使用"Pieces"库轻松实现动画片段幻灯片效果. 今天我们想向 ...

  5. Javascript设计模式之发布-订阅模式

    简介 发布-订阅模式又叫做观察者模式,他定义了一种一对多的依赖关系,即当一个对象的状态发生改变的时候,所有依赖他的对象都会得到通知. 回忆曾经 作为一名前端开发人员,给DOM节点绑定事件可是再频繁不过 ...

  6. jquery undelegate()方法 语法

    jquery undelegate()方法 语法 作用:undelegate() 方法删除由 delegate() 方法添加的一个或多个事件处理程序.大理石平台支架 语法:$(selector).un ...

  7. noi.ac #528 神树和排列

    题目链接:戳我 #include<iostream> #include<cstring> #include<cstdio> #include<algorith ...

  8. Python基础之注释

    有时候我们写的东西不一定都是给用户看的,或者不希望解释器执行,那么我们可以选择注释掉代码. 被注释的内容是不会执行的,可以方便在以后能读懂代码. 注释分为两种,一种是单行注释,一种是多行注释. 单行注 ...

  9. docker Swarm mode集群

    基本概念 Swarm 是使用 SwarmKit 构建的 Docker 引擎内置(原生)的集群管理和编排工具. 使用 Swarm 集群之前需要了解以下几个概念. 节点 运行 Docker 的主机可以主动 ...

  10. linux调用本地shell脚本

    package com.haiyisoft.cAssistant.adapter.rest; import java.io.BufferedReader;import java.io.File;imp ...