加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

day96:flask:flask-migrate&flask-session&蓝图Bl

发布时间:2020-12-20 09:59:34 所属栏目:Python 来源:网络整理
导读:目录 1.flask-migrate 2.flask-session 3.蓝图:Blueprint 4.蓝图的运行机制 5.基于flask仿照django进行项目架构 1.准备工作 2.加载配置文件 3.生成蓝图 4.路由-视图路由分发 5.模型类和数据库迁移 1.数据库迁移:flask-migrate 1.Flask的数据库迁移 在开发过

目录

1.flask-migrate

2.flask-session

3.蓝图:Blueprint

4.蓝图的运行机制

5.基于flask仿照django进行项目架构

  1.准备工作

  2.加载配置文件

  3.生成蓝图

  4.路由-视图&路由分发

  5.模型类和数据库迁移

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  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-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的基本配置

 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()

执行程序,访问127.0.0.1:5000,即可将session值存储到redis中

如图所示:

3.SQLAlchemy存储session的基本配置

 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()

执行程序,访问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文件中创建蓝图对象

 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.users/__init__.py中引入views.py中所有的视图函数

 3. 注册视图
from .views import *

4.在主应用main.py文件中的app对象上注册这个users蓝图对象

 4. 注册蓝图
from users  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目录设置为静态目录

 通过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.蓝图运行机制的简要介绍

  • 蓝图是保存了一组将来可以在应用对象上执行的操作,注册路由就是一种操作

  • 当在app对象上调用 route 装饰器注册路由时,这个操作将修改对象的url_map路由表

  • 然而,蓝图对象根本没有路由表,当我们在蓝图对象上调用route装饰器注册路由时,它只是在内部的一个延迟操作记录列表defered_functions中添加了一个项

  • 当执行app对象的 register_blueprint() 方法时,应用对象将从蓝图对象的 defered_functions 列表中取出每一项,并以自身作为参数执行该匿名函数,即调用应用对象的 add_url_rule() 方法,这将真正的修改应用对象的usr_map路由表

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


       ......

        ")

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读