day96:flask:flask-migrate&flask-session&蓝图Blueprint&蓝图的运行机制
目录
1.数据库迁移:flask-migrate
1.Flask的数据库迁移
在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。
更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。
在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。并且集成到Flask-Script中,所有操作通过命令就能完成。
为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可以附加到flask-script的manager对象上。
2.flask-migrate的安装
pip install flask-migrate
3.在flask代码中引入数据库迁移
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand # 1.引入Migrate和MigrateCommand
from flask_script import Manager,Command app = Flask(__name__,template_folder='templates')
app.config.from_object(Config) manage = Manager(app) db = SQLAlchemy(app) # 2.创建migrate对象。第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例
migrate = Migrate(app,db) # 3.manager是Flask-Script的实例,这条语句在flask-Script中添加一个db命令
manage.add_command('db',MigrateCommand) achieve = db.Table('tb_achievement',
db.Column('student_id', db.Integer, db.ForeignKey('tb_student.id')),
db.Column('course_id', db.Integer, db.ForeignKey('tb_course.id'))
) class Course(db.Model):
__tablename__ = 'tb_course'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
price = db.Column(db.Numeric(6,2))
teacher_id = db.Column(db.Integer, db.ForeignKey('tb_teacher.id'))
students = db.relationship('Student', secondary=achieve, backref='courses', lazy='subquery') def __repr__(self):
return 'Course:%s'% self.name class Student(db.Model):
__tablename__ = 'tb_student'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
email = db.Column(db.String(64),unique=True)
age = db.Column(db.SmallInteger,nullable=False)
sex = db.Column(db.Boolean,default=1) def __repr__(self):
return 'Student:%s' % self.name class Teacher(db.Model):
__tablename__ = 'tb_teacher'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
courses = db.relationship('Course', backref='teacher', lazy='subquery') def __repr__(self):
return 'Teacher:%s' % self.name @app.route("/")
def index():
return "ok" if __name__ == '__main__':
manage.run()
4.flask中数据库迁移常用的命令
1.创建迁移版本仓库
# 这个命令会创建migrations文件夹,所有迁移文件都放在里面。
python main.py db init
2.创建迁移版本仓库
# 这里等同于django里面的 makemigrations,生成迁移版本文件
python main.py db migrate -m 'initial migration'
3.升级迁移版本库的版本
python main.py db upgrade
4.降级迁移版本库的版本
python main.py db downgrade
5.回滚到指定版本
python manage.py db downgrade 版本号 # 返回到指定版本号对应的版本
6.查看数据库迁移历史(可查看数据库迁移版本号)
python manage.py db history # 输出格式:<base> -> 版本号 (head), initial migration
一般数据迁移的步骤是:init-->migrate-->upgrade/downgrade
2.flask-session
flask-session:允许设置session到指定存储的空间中
安装命令: https://pythonhosted.org/Flask-Session/
1.flask-session的安装和配置
pip install flask-Session
使用session之前,必须配置一下配置项:
SECRET_KEY = "*(%#4sxcz(^(#$#8423" # session秘钥
2.redis保存session的基本配置
from flask import Flask,session
from flask_redis import FlaskRedis
from flask_session import Session
app = Flask(__name__)
redis = FlaskRedis()
session_store = Session()
class Config():
# DEBUG调试模式
DEBUG = True # json多字节转unicode编码
JSON_AS_ASCII = False # 数据库链接配置
SECRET_KEY = "*(%#4sxcz(^(#$#8423" # 1.session存储方式为redis
SESSION_TYPE = "redis" # 2.session保存数据到redis时启用的链接对象
SESSION_REDIS = redis # 3.如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效
SESSION_PERMANENT = True # 4.是否对发送到浏览器上session的cookie值进行加密
SESSION_USE_SIGNER = True # 5.保存到redis的session数的名称前缀
SESSION_KEY_PREFIX = "session:" # 6.redis的链接配置
REDIS_URL = "redis://localhost:6379/1" app.config.from_object(Config) # 将Config类注册到app上
redis.init_app(app) # 将flask-redis对象挂载到app上
session_store.init_app(app) # 将flask-session对象挂载到app上 @app.route("/")
def index():
session["username"] = "xiaoming"
return "Ok" @app.route("/get_session")
def get_session():
print( session["username"] )
return "ok" @app.route("/redis1")
def set_redis():
# redis给集合数据类型/哈希数据类型设置值
redis.set("username","xiaohuihui")
redis.hset("brother","zhangfei","17")
return "ok" @app.route("/redis2")
def get_redis():
user = redis.get("username").decode() brother = redis.hgetall("brother")
print(brother["zhangfei".encode()].decode()) return "ok" if __name__ == '__main__':
app.run()
执行程序,访问127.0.0.1:5000,即可将session值存储到redis中
如图所示:
3.SQLAlchemy存储session的基本配置
from flask import Flask,session
from flask_redis import FlaskRedis
from flask_session import Session
from flask_sqlalchemy import SQLAlchemy app = Flask(__name__)
db = SQLAlchemy()
redis = FlaskRedis()
session_store = Session() class Config(): ......
'''数据库链接配置'''
# SQLALCHEMY_DATABASE_URI = "mysql://账号:密码@IP/数据库名?编码"
SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4" # 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = True # 查询时会显示原始SQL语句
SQLALCHEMY_ECHO = True '''数据库保存session'''
SESSION_TYPE = 'sqlalchemy' # session类型为sqlalchemy
SESSION_SQLALCHEMY = db # SQLAlchemy对象
SESSION_SQLALCHEMY_TABLE = 'tb_session' # session要保存的表名称
SESSION_PERMANENT = True # 如果设置为True,则关闭浏览器session就失效。
SESSION_USE_SIGNER = False # 是否对发送到浏览器上session的cookie值进行加密
SESSION_KEY_PREFIX = 'session:' # 保存到session中的值的前缀 db.init_app(app)
app.config.from_object(Config)
redis.init_app(app)
session_store.init_app(app) @app.route("/")
def index():
session["username"] = "xiaohui"
return "Ok" @app.route("/get_session")
def get_session():
return session["username"] if __name__ == '__main__':
# with app.app_context():
# db.create_all()
app.run()
执行程序,访问127.0.0.1:5000,即可将session值存储到mysql中
如图所示:
3.蓝图:Blueprint
1.蓝图:模块化
随着flask程序越来越复杂,我们需要对程序进行模块化的处理,之前学习过python的模块化管理,于是针对一个简单的flask程序进行模块化处理
简单来说,Blueprint 是一个存储视图方法的容器,这些操作在这个Blueprint 被注册到一个应用之后就可以被调用,Flask 可以通过Blueprint来组织URL以及处理请求。
Flask使用Blueprint让应用实现模块化,在Flask中,Blueprint具有如下属性:
一个项目可以具有多个Blueprint
可以将一个Blueprint注册到任何一个未使用的URL下比如 “/”、“/sample”或者子域名
在一个应用中,一个模块可以注册多次
Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
在一个应用初始化时,就应该要注册需要使用的Blueprint
但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。
Blueprint对象用起来和一个应用/Flask对象差不多,最大的区别在于一个 蓝图对象没有办法独立运行,必须将它注册到一个应用对象上才能生效.
2.简单使用蓝图
1.创建一个蓝图的包,例如users,并在__init__.py
文件中创建蓝图对象
from flask import Blueprint
# 1. 创建蓝图目录并对蓝图对象进行初始化
users_blue = Blueprint("users",__name__,template_folder="users_templates",static_folder='users_static',static_url_path="/libs")
2.在这个蓝图目录下, 创建views.py文件,保存当前蓝图使用的视图函数
from . import users_blue
from flask import render_template
# 2. 编写视图
@users_blue.route("/")
def index():
return render_template("index.html",title="users/index/index.html") @users_blue.route("/list")
def list():
return "users/list"
3.在users/__init__.py中引入views.py中所有的视图函数
# 3. 注册视图
from .views import *
4.在主应用main.py文件中的app对象上注册这个users蓝图对象
# 4. 注册蓝图
from users import users_blue
app.register_blueprint(users_blue,url_prefix="/users")
当这个应用启动后,通过/users/可以访问到蓝图中定义的视图函数
3.蓝图的url前缀
当我们在应用对象上注册一个蓝图时,可以指定一个url_prefix关键字参数(这个参数默认是/)
在应用最终的路由表 url_map中,在蓝图上注册的路由URL自动被加上了这个前缀,这个可以保证在多个蓝图中使用相同的URL规则而不会最终引起冲突,只要在注册蓝图时将不同的蓝图挂接到不同的自路径即可
url_for在使用时,如果要生成一个蓝图里面的视图对应的路由地址,则需要声明当前蓝图名称+视图名称
url_for('users.home') # /users/home
4.注册蓝图的静态文件的相关路由
1.static_folder:设置静态文件目录
和应用对象不同,蓝图对象创建时不会默认注册静态目录的路由。需要我们在 创建时指定 static_folder 参数。
下面的示例将蓝图所在目录下的static_users目录设置为静态目录
from flask import Blueprint
# 通过static_folder参数设置静态文件目录
users_blue = Blueprint("users",__name__,static_folder='users_static')
2.static_url_path:改变静态文件的路由
定制静态目录URL规则 :可以在创建蓝图对象时使用 static_url_path 来改变静态目录的路由。
下面的示例将为 users/static 文件夹的路由设置为 /lib
from flask import Blueprint
# 通过static_url_path设置静态文件路由
users_blue = Blueprint("users",__name__,static_folder='users_static',static_url_path='/lib')
访问http://127.0.0.1:5000/users/libs/1.jpg 即可查看到图片
5.设置蓝图中模板的目录
蓝图对象默认的模板目录为系统的模版目录,可以在创建蓝图对象时使用 template_folder 关键字参数设置模板目录
users_blue = Blueprint("users",__name__,static_folder='users_static',static_url_path='/libs',template_folder='users_templates')
注意:如果在 templates 中存在和 templates_users 有同名模板文件时, 则系统会优先使用 templates 中的文件
4.蓝图的运行机制
1.蓝图运行机制的简要介绍
蓝图是保存了一组将来可以在应用对象上执行的操作,注册路由就是一种操作
当在app对象上调用 route 装饰器注册路由时,这个操作将修改对象的url_map路由表
然而,蓝图对象根本没有路由表,当我们在蓝图对象上调用route装饰器注册路由时,它只是在内部的一个延迟操作记录列表defered_functions中添加了一个项
当执行app对象的 register_blueprint() 方法时,应用对象将从蓝图对象的 defered_functions 列表中取出每一项,并以自身作为参数执行该匿名函数,即调用应用对象的 add_url_rule() 方法,这将真正的修改应用对象的usr_map路由表
2.蓝图运行机制的详细介绍
day96:flask:flask-migrate&flask-session&蓝图Blueprint&蓝图的运行机制的更多相关文章
- 第九篇 Flask 中的蓝图(BluePrint)
第九篇 Flask 中的蓝图(BluePrint) 蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? ...
- Flask路由与蓝图Blueprint
需求分析: 当一个庞大的系统中有很多小模块,在分配路由的时候怎么处理呢?全部都堆到一个py程序中,调用@app.route? 显然这是很不明智的,因为当有几十个模块需要写路由的时候,这样程序员写着写着 ...
- Flask 中的蓝图(BluePrint)
蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开 怎么理解呢? 比如说,你有一个客户管理系统,最开始的时候,只有一个查 ...
- 用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 Blueprint 蓝图 定义一个蓝图 注册一个蓝图 创建蓝 ...
- python 全栈开发,Day120(路由系统, 实例化Flask的参数, 蓝图(BluePrint), before_request after_request)
昨日内容回顾 1.Flask: from flask import Flask app = Flask(__name__) # 从源码中可以看出,Flask集成的run方法是由werkzeug中的ru ...
- Flask蓝图Blueprint和特殊装饰器
Flask 中的 蓝图 Blueprint 不能被run的flask实例:相当于django中的app01 应用 蓝图作用:功能隔离 路由隔离 Blueprint就是 一个不能run的flask 蓝图 ...
- Flask 蓝图(Blueprint)
蓝图使用起来就像应用当中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝图之间互相不影响.但是它们又属于应用中,可以共享应用的配置.对于大型应用来说,我们可以通过添加蓝图来扩 ...
- flask Blueprint蓝图
首先要了解蓝图的作用,模拟场景在团队开发过程中团队每个人都在写自己负责的功能模块,那多个py文件模板,我们如果完成后需要运行是不是要运行多个服务?但是我们的项目是一个整体,而不是零散的,所以我们怎么把 ...
- Flask最强攻略 - 跟DragonFire学Flask - 第九篇 Flask 中的蓝图(BluePrint)
蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? 比如说,你有一个客户管理系统,最开始的时候,只有一个查看 ...
随机推荐
- Angular双向绑定简单理解
在使用Antd的时候,一直很好奇里面的双向绑定的自定义组件是怎么做的. 因为之前一直用,没有去细看文档. 今天抽空来简单的撸一下. 在ng中,()是单向数据流,从视图目标到数据源,[()]这样就是双向 ...
- 【Flutter 面试】main入口函数会被调用几次
老孟导读:这是一个读者面试时被问到的问题,这个问题前段时间我也在VIP交流群和大家一起探讨过. 这个问题涉及引擎的相关知识,如果不了解相关知识,很难回答正确,因为不管说调用几次都是错误的,下面来看一下 ...
- H5页面 用户启动无痕浏览本地储存 localstorage 清楚数据
移动端开发时,如果用户浏览器启用了无痕浏览,那么本地存储信息就会失效,会导致页面信息报错 解决办法: 先判断是否能适用 localStorage.setItem 如果不行在适用 cookie coo ...
- Udacity的C++编程练习: Python转C++
练习 1 在机器人定位的课程中,Sebastian Thrun 已经带领你了解了一维机器人传感和运动的 Python 代码.最后你得到了一个 sense() 函数,它基于传感器的测量数据来更新概率.你 ...
- CentOS7 安装telnet-0.17-64.el7.x86_64
1.安装客服端,服务端,xinetd yum -y install telnet telnet-server xinetd 以上要想完成telnet安装,telnet服务端和xinetd必须安装,至于 ...
- SQL Server 列存储索引 第三篇:维护
列存储索引分为两种类型:聚集的列存储索引和非聚集的列存储索引,在一个表上只能创建一个聚集索引,要么是聚集的列存储索引,要么是聚集的行存储索引,然而一个表上可以创建多个非聚集索引. 一,创建列存储索引 ...
- python使用pandas进行数据处理
pandas数据处理 关注公众号"轻松学编程"了解更多. 以下命令都是在浏览器中输入. cmd命令窗口输入:jupyter notebook 打开浏览器输入网址http://loc ...
- 使用IDEA完成一个SpringBoot的demo
打算开始做毕业设计了,写一些博客记录一下做毕业设计的过程. 前两天从老师那里拿了学长学姐做的非常简陋的代码,配置环境跑了一下,老师找我的时候说还剩下50%的工作,但感觉至少还有70%. 废话不多说,今 ...
- 基于synchronized锁的深度解析
1. 问题引入 小伙伴们都接触过线程,也都会使用线程,今天我们要讲的是线程安全相关的内容,在这之前我们先来看一个简单的代码案例. 代码案例: /** * @url: i-code.online * @ ...
- 小学生学习C++应该具备哪些基础?
一.电脑操作基础: 应该具备一些必要的电脑相关的知识,如操作系统的相关知识,如何打开.编辑.保存文件.对电脑的能力有一些基本的认识,以及会使用鼠标,键盘熟练输入. 磨刀不误砍柴工,至少要做到能快速找到 ...