day96:flask:flask-migrate&flask-session&蓝图Bl
目录1.flask-migrate 2.flask-session 3.蓝图:Blueprint 4.蓝图的运行机制 5.基于flask仿照django进行项目架构 1.准备工作 2.加载配置文件 3.生成蓝图 4.路由-视图&路由分发 5.模型类和数据库迁移 1.数据库迁移:flask-migrate1.Flask的数据库迁移
2.flask-migrate的安装pip install flask-migrate 3.在flask代码中引入数据库迁移from flask import Flask from config Config from flask_sqlalchemy SQLAlchemy from flask_migrate import Migrate,MigrateCommand # 1.引入Migrate和MigrateCommand from flask_script 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_achievementstudent_id',db.Integer,db.ForeignKey(tb_student.id)),1)">course_idtb_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,1)">tb_teacher.id)) students = db.relationship(Studentcoursessubquery) def __repr__(self): return Course:%s'% self.name Student(db.Model): tb_studentTrue) email = db.Column(db.String(64),1)">True) age = db.Column(db.SmallInteger,nullable=False) sex = db.Column(db.Boolean,default=1Student:%s' % Teacher(db.Model): tb_teacherTrue) courses = db.relationship(CourseteacherTeacher:%s self.name @app.route("/") def index(): 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-sessionflask-session:允许设置session到指定存储的空间中
pip install flask-Session 使用session之前,必须配置一下配置项: SECRET_KEY = *(%#4sxcz(^(#$#8423" session秘钥 2.redis保存session的基本配置Flask,session from flask_redis FlaskRedis from flask_session Session app = Flask(__name__) redis = FlaskRedis() session_store = Session() Config(): DEBUG调试模式 DEBUG = True json多字节转unicode编码 JSON_AS_ASCII = False 数据库链接配置 SECRET_KEY = " 1.session存储方式为redis SESSION_TYPE = redis 2.session保存数据到redis时启用的链接对象 SESSION_REDIS = redis 3.如果设置session的生命周期是否是会话期,为True,则关闭浏览器session就失效 SESSION_PERMANENT = 4.是否对发送到浏览器上session的cookie值进行加密 SESSION_USE_SIGNER = 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( index(): session[username"] = xiaoming" Ok/get_session get_session(): print( session[] ) /redis1 set_redis(): redis给集合数据类型/哈希数据类型设置值 redis.set(",xiaohuihui) redis.hset(brotherzhangfei17) /redis2 get_redis(): user = redis.get().decode() brother = redis.hgetall(print(brother[.encode()].decode()) : app.run()
Session SQLAlchemy app = Flask() db = SQLAlchemy() redis = Session() 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中的值的前缀 db.init_app(app) app.config.from_object(Config) redis.init_app(app) session_store.init_app(app) @app.route(xiaohuireturn session[] : with app.app_context(): db.create_all() app.run()
简单来说,Blueprint 是一个存储视图方法的容器,这些操作在这个Blueprint 被注册到一个应用之后就可以被调用,Flask 可以通过Blueprint来组织URL以及处理请求。 Flask使用Blueprint让应用实现模块化,在Flask中,Blueprint具有如下属性:
但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。 Blueprint对象用起来和一个应用/Flask对象差不多,最大的区别在于一个 蓝图对象没有办法独立运行,必须将它注册到一个应用对象上才能生效. 2.简单使用蓝图1. Blueprint 1. 创建蓝图目录并对蓝图对象进行初始化 users_blue = Blueprint(usersusers_templatesusers_static/libs") 2.在这个蓝图目录下,创建views.py文件,保存当前蓝图使用的视图函数 from . users_blue render_template 2. 编写视图 @users_blue.route(return render_template(index.htmlusers/index/index.html) @users_blue.route(/list list(): users/list" 3. 3. 注册视图 from .views import * 4. 4. 注册蓝图 from users users_blue app.register_blueprint(users_blue,url_prefix=/users") 当这个应用启动后,通过/users/可以访问到蓝图中定义的视图函数 3.蓝图的url前缀当我们在应用对象上注册一个蓝图时,可以指定一个url_prefix关键字参数(这个参数默认是/)
url_for(users.home') /users/home 4.注册蓝图的静态文件的相关路由1.static_folder:设置静态文件目录
下面的示例将蓝图所在目录下的static_users目录设置为静态目录 通过static_folder参数设置静态文件目录 users_blue = Blueprint(') ? 2.static_url_path:改变静态文件的路由定制静态目录URL规则 :可以在创建蓝图对象时使用 static_url_path 来改变静态目录的路由。 下面的示例将为 users/static 文件夹的路由设置为 /lib ? 通过static_url_path设置静态文件路由 users_blue = Blueprint(/lib') 访问http://127.0.0.1:5000/users/libs/1.jpg 即可查看到图片 5.设置蓝图中模板的目录蓝图对象默认的模板目录为系统的模版目录,可以在创建蓝图对象时使用 template_folder 关键字参数设置模板目录 users_blue = Blueprint(')
注意:如果在 templates 中存在和 templates_users 有同名模板文件时,则系统会优先使用 templates 中的文件 4.蓝图的运行机制1.蓝图运行机制的简要介绍
2.蓝图运行机制的详细介绍5. 基于flask仿照django进行项目架构1.准备工作1.在项目中创建manage.py作为项目的启动文件 2.确定项目的目录结构 3.在application的__init__.py中,实例化flask对象和终端脚本管理对象Manager 并在最后将manager终端管理对象返回出来 Manager 创建应用对象 app = Flask() 创建终端脚本管理对象 manager = Manager() init_app(): 挂载应用对象 manager.app = app 对外暴露终端管理对象 return manager 4.在manager.py中,只做一件事:就是运行项目 from application init_app manager = init_app(: manager.run() 2.加载配置文件1.在项目的application文件夹中创建settings文件夹,用来存放配置信息。 2.我们将一些公共的配置写在settings/__init__.py中 InitConfig(): DEBUG = True 总路由的地址 URL_PATH = application.urls 蓝图列表 INSTALLED_APPS = [ ] 数据库链接配置 "" 查询时会显示原始SQL语句 SQLALCHEMY_ECHO = True 3.将本地开发配置文件写在dev.py中 创建一个配置类,要继承我们上面写的公共配置类 InitConfig Config(InitConfig): """本地开发配置文件""" INSTALLED_APPS = [ application.apps.homeapplication.apps.users 数据库链接配置 SQLALCHEMY_DATABASE_URI = " 4.将线上运营配置文件写在prod.py中 --------------------------------- 现在配置文件的目录包括里面的相关内容都已经写好了,那么如何在项目当中使用我们已经写好的配置呢? init_app 将我们的dev配置文件加载进来 manager = init_app(application.settings.dev: manager.run() application.settings.dev作为init_app的参数被传了进来,所以我们在application/__init__.py中定义的init_app方法也要添加这个参数 现在的问题是:我们可不可以基于这个config_path来完成自动加载配置文件的信息呢? 1.在application中创建utils文件夹,并在utils中的__init__.py定义load_config方法 load_config(config_path): 自动加载配置""" import_module 根据字符串路径直接进行模块导包,识别模块中的变量成员 module = import_module(config_path) 获取配置文件路径的最后一段: 1.如果是settings 加载的就是公共配置类 2.如果不是settings,那么按照现在来说,必然是dev或者prod config_file_name = config_path.split(.")[-1] if config_file_name == settings: return module.InitConfig 后缀是settings,返回公共配置类 return module.Config 后缀是dev/prod,返回自己的config类 2.在application中的__init__.py中增添如下代码,让APP初始化的时候自动将你在manager.py中传入的配置文件中的类加载进去。 自动加载配置 Config = load_config(config_path) 通过自己定义的加载配置类方法,可得到应该加载的配置类是哪个类 app.config.from_object(Config) 将配置类注册到app上 return manager 3.生成蓝图1.在application中创建apps,用来存放各个蓝图。 那么我们如何通过输入命令来自动创建蓝图,并在创建的蓝图中存在默认的model,view,url等文件呢? 在utils创建command.py文件,定义BluePrintCommand类,来实现通过命令创建蓝图并生成蓝图内部的相关文件 Command,Option os BluePrintCommand(Command): name = blue" 命令的调用别名 option_list = [ Option(--name-n蓝图名称) ] def run(self,name=None): if name is None: print(蓝图名称不能为空!) return if not os.path.isdir(name): os.mkdir(name) open(%s/views.py" % name,1)">w) open(%s/models.py) with open(%s/urls.py) as f: f.write(from . import views urlpatterns = [ ] """) 2.自定义的命令已经写好了,那么如何才能让系统自动加载我们自定义的命令呢?这就需要在util/__init__.py中定义一个自动加载命令的方法了 load_command(manager,command_path): 自动加载命令 module = import_module(command_path) 搜索当前模块下的所有类 class_list = inspect.getmembers(module,inspect.isclass) for class_name,class_object in class_list: if issubclass(class_object,Command) and class_name != Command: manager.add_command(class_object.name,class_object) 3.在application的__init__.py中,让其自动加载我们自定义的终端命令 app 自动加载终端命令 *** load_command(manager,1)">application.utils.commandsreturn manager 4.现在我们在输入命令:python ../../ manager.py blue -n=home 即可在app目录下创建一个名字为home的蓝图 4.路由-视图&路由分发1.之前我们在django的时候,在urls.py中写上path(路由,视图函数)即可实现路由和视图函数的关联 那如果自己去手动实现这个功能,应该怎样去做呢? 1.首先,在urls.py中,是有一个path方法的,里面有两个参数,一个是路由,一个是视图函数 那我们就在utils的__init__.py中定义一个path方法,path方法只做一件事:接收参数,并返回一个字典。 path(url,view_func): 注册路由return {rule":url,1)">view_func":view_func} 2.自动加载蓝图对象 在自动加载蓝图的方法中,做了如下几件事: 1.在创建蓝图对象的时候,自动注册路由【通过当前蓝图对象.add_url_rule(url,view_func)来实现】 load_blueprint(app,db): 自动加载蓝图""" 在从配置中根据INSTALLED_APPS进行循环,在循环中进行蓝图的注册 for blueprint_path in app.config.get(INSTALLED_APPS): 获取蓝图名称 blueprint_name = blueprint_path.split(] 创建蓝图对象 blue = Blueprint(blueprint_name,blueprint_path) 蓝图对象自动注册路由 blue_urls_module = import_module(blueprint_path+.urls) for urls_item blue_urls_module.urlpatterns: blue.add_url_rule(**urls_item) 注册蓝图 app.register_blueprint(blue,url_prefix="") 2.我们可能会遇到不同蓝图中有相同url路径的情况,为了对他们加以区分,我们应该对url再加上一个前缀 比如:/home/index和/users/index 所以需要加载蓝图的时候,自动添加一个前缀 首先,在utils下的__init__.py中定义include方法,用来进行路由分发 include(url,blueprint_path): url_prefixpath": blueprint_path} 然后获取蓝图的url前缀(前缀就是蓝图名称) app_url_list = import_module(app.config.get(URL_PATH")).urlpatterns application.urls.urlspatterns for blueprint_url app_url_list: if blueprint_url.get(") == blueprint_name+: url_prefix = blueprint_url.get() break 创建蓝图对象 blue = Blueprint(blueprint_name,blueprint_path) 蓝图对象自动注册路由 blue_urls_module = import_module(blueprint_path+".urls") for urls_item in blue_urls_module.urlpatterns: blue.add_url_rule(**urls_item) url_prefix) 加载当前蓝图下的模型 import_module(blueprint_path+.models") 注意:先提前在配置类中写上这个,这样?app.config.get("URL_PATH") 才能获取到 InitConfig(): " 5.模型类和数据库迁移application/__init__.py init_app(config_path): ...... 数据迁移初始化 migrate.init_app(app,db) manager.add_command(return manager 如果我们在application/apps/home/models.py写入一个模型类,然后执行数据库迁移指令,发现是无法进行数据库迁移的 原因是识别不到你在蓝图内定义的模型类。那怎样能让其识别你在蓝图中定义的模型类呢? 我们需要在注册蓝图之后中加载当前蓝图下的模型 utils/__init__.py ...... ") ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |