• 10-flask框架-数据库迁移/session存储/faker模块/配置项写法


    一、数据库迁移

    • 在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。

    • 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。

    • 在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。并且集成到Flask-Script中,所有操作通过命令就能完成。

    • 为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可以附加到flask-script的manager对象上。

    首先要在虚拟环境中安装Flask-Migrate

    pip install flask-migrate

    代码 manage.py文件内容:

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    
    class Config(object):
        DEBUG = True
        # 数据库连接配置
        # SQLALCHEMY_DATABASE_URI = "数据库类型://数据库账号:密码@数据库地址:端口/数据库名称?charset=utf8mb4"
        SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
        # 动态追踪修改设置,如未设置只会提示警告
        SQLALCHEMY_TRACK_MODIFICATIONS = True
        # 查询时会显示原始SQL语句
        SQLALCHEMY_ECHO = True
    
    app.config.from_object(Config)
    db = SQLAlchemy(app=app)
    
    # 初始化数据迁移工具
    # 初始化完成以后,由Migrate会在系统终端下创建 flask db 的迁移命令
    
    from flask_migrate import Migrate
    migrate = Migrate()
    migrate.init_app(app=app,db=db)
    
    """模型类定义"""
    # 多对多关系表
    achievement = db.Table(
        'db_achievement',
        db.Column('id', db.Integer, primary_key=True),
        db.Column('student_id', db.Integer, db.ForeignKey('db_students.id')),
        db.Column('course_id', db.Integer, db.ForeignKey('db_course.id')),
    )
    
    class Student(db.Model):
        """学生信息模型"""
        __tablename__ = "db_students"
        id = db.Column(db.Integer, primary_key=True,comment="主键")
        name = db.Column(db.String(15), comment="姓名")
        age = db.Column(db.SmallInteger, comment="年龄")
        sex = db.Column(db.Boolean, default=True, comment="性别")
        email = db.Column(db.String(128), comment="邮箱地址")
        money = db.Column(db.Numeric(10,2), default=0.0, comment="钱包")
        course_list = db.relationship("Course",secondary=achievement, backref="student_list", lazy="dynamic")
    
        def __repr__(self):
            return f"{self.name}<Student>"
    
    class Course(db.Model):
        """课程数据模型"""
        __tablename__ = "db_course"
        id = db.Column(db.Integer, primary_key=True, comment="主键")
        name = db.Column(db.String(64), unique=True, comment="课程")
        price = db.Column(db.Numeric(7, 2))
        cover = db.Column(db.String(255), comment="封面图片")
        desc  = db.Column(db.String(255), comment="课程介绍")
        def __repr__(self):
            return f'{self.name}<Course>'
    
    
    @app.route("/")
    def index():
        return "ok"
    
    if __name__ == '__main__':
        app.run()

    创建迁移版本仓库

    # 切换到项目根目录下,
    cd ~/Desktop/flaskdemo
    # 设置flask项目的启动脚本位置
    # 新版本的flask1.1,会在系统终端下提供一个类似django-admin的终端命令工具, 可以实现类似 flask_scipt 的功能
    export FLASK_APP=manage.py
    # flask run 启动flask项目
    # 数据库迁移初始化,这个命令会在当前项目根目录下创建migrations文件夹,所有数据表相关的迁移文件都放在里面。
    flask db init

    创建迁移版本

    • 自动创建迁移版本有两个函数

      • upgrade():函数把迁移中的改动应用到数据库中。

      • downgrade():函数则将改动删除。

    • 自动创建的迁移脚本会根据模型定义和数据库当前状态的差异,生成upgrade()和downgrade()函数的内容。

    • 对比不一定完全正确,有可能会遗漏一些细节,需要进行检查

    # 根据flask项目的模型生成迁移文件
    flask db migrate -m 'initial migration'
    # 这里等同于django里面的 makemigrations,生成迁移版本文件
    # 完成2件事情:
    # 1. 在migrations/versions生成一个数据库迁移文件
    # 2. 如果是首次生成迁移文件的项目,则迁移工具还会在数据库创建一个记录数据库版本的version表

    升级版本库的版本

    # 从migations目录下的versions中根据迁移文件upgrade方法把数据表的结构同步到数据库中。
    flask db upgrade

    降级版本库的版本

    # 从migations目录下的versions中根据迁移文件downgrade把数据表的结构同步到数据库中。
    flask db downgrade

    版本库的历史管理

    可以根据history命令找到版本号,然后传给downgrade命令:

    flask db history
    
    输出格式:<base> ->  版本号 (head), initial migration

    回滚到指定版本

    flask db downgrade # 默认返回上一个版本
    flask db downgrade 版本号   # 回滚到指定版本号对应的版本
    flask db upgrade 版本号     # 升级到指定版本号对应的版本

    数据迁移的步骤:

    1. 初始化数据迁移的目录
    export FLASK_APP=manage.py
    flask db init
    
    2. 数据库的数据迁移版本初始化
    flask db migrate -m 'initial migration'
    
    3. 升级版本[创建表/创建字段/修改字段]
    flask db upgrade 
    
    4. 降级版本[删除表/删除字段/恢复字段]
    flask db downgrade

    二、模块推荐faker

    文档: https://faker.readthedocs.io/en/master/locales/zh_CN.html

    批量生成测试数据: https://github.com/joke2k/faker

    pip install faker -i https://pypi.douban.com/simple

    代码:

     1 from flask import Flask
     2 from flask_sqlalchemy import SQLAlchemy
     3 
     4 app = Flask(__name__)
     5 
     6 class Config(object):
     7     DEBUG = True
     8     # 数据库连接配置
     9     # SQLALCHEMY_DATABASE_URI = "数据库类型://数据库账号:密码@数据库地址:端口/数据库名称?charset=utf8mb4"
    10     SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    11     # 动态追踪修改设置,如未设置只会提示警告
    12     SQLALCHEMY_TRACK_MODIFICATIONS = True
    13     # 查询时会显示原始SQL语句
    14     SQLALCHEMY_ECHO = True
    15 
    16 app.config.from_object(Config)
    17 db = SQLAlchemy(app=app)
    18 
    19 class Student(db.Model):
    20     """学生信息模型"""
    21     __tablename__ = "db_students"
    22     id = db.Column(db.Integer, primary_key=True,comment="主键")
    23     name = db.Column(db.String(15), comment="姓名")
    24     age = db.Column(db.SmallInteger, comment="年龄")
    25     sex = db.Column(db.Boolean, default=True, comment="性别")
    26     email = db.Column(db.String(128), comment="邮箱地址")
    27     money = db.Column(db.Numeric(10,2), default=0.0, comment="钱包")
    28 
    29     def __repr__(self):
    30         return f"{self.name}<Student>"
    31 
    32 from flask_script import Command,Manager,Option
    33 
    34 manage = Manager()
    35 manage.app = app
    36 
    37 # 自定义批量生成学生
    38 import random
    39 from faker import Faker
    40 class FakerStudentCommand(Command):
    41     """生成测试学生信息"""
    42     Name = "student"
    43     option_list = (
    44         Option("-n","--num",dest="num", type=int),
    45     )
    46 
    47     def run(self,num):
    48         faker = Faker(locale="ZH_CN")
    49         for i in range(num):
    50             sex = bool( random.randint(0,1) )
    51             student = Student(
    52                 name= faker.name_male() if sex else faker.name_female(),
    53                 age=random.randint(15,60),
    54                 sex=sex,
    55                 email=faker.free_email(),
    56                 money= float( random.randint(100,100000) / 100 ),
    57             )
    58             db.session.add(student)
    59         # 在循环外面统一提交
    60         db.session.commit()
    61 
    62 manage.add_command(FakerStudentCommand.Name, FakerStudentCommand)
    63 
    64 @app.route("/")
    65 def index():
    66     return "ok"
    67 
    68 if __name__ == '__main__':
    69     manage.run()
    View Code

    三、flask-session

    session如如果不设置默认存储到系统的文件中,通过此模块允许设置session到指定存储的空间中, 文档:

    安装命令: https://pythonhosted.org/Flask-Session/

    pip install flask-session

    使用session之前,必须配置一下配置项:

    SECRET_KEY = "*(%#4sxcz(^(#$#8423" # session秘钥

    3.1 SQLAlchemy存储session的基本配置

     需要手动创建session表,在项目第一次启动的时候,使用db.create_all()来完成创建。

    只要配置项:

    # 把session通过SQLAlchmey保存到mysql中
    SESSION_TYPE = "sqlalchemy" # session类型为sqlalchemy
    SESSION_SQLALCHEMY = db     # SQLAlchemy对象
    SESSION_SQLALCHEMY_TABLE = 'db_session' # session要保存的表名称
    SESSION_PERMANENT = True    # 如果设置为True,则关闭浏览器session就失效
    SESSION_USE_SIGNER =  False  # 是否对发送到浏览器上session的cookie值进行加密
    SESSION_KEY_PREFIX = "session:" # sessionID的前缀,默认就是 session:
     1 from flask import Flask
     2 from flask_sqlalchemy import SQLAlchemy
     3 from flask_session import Session
     4 app = Flask(__name__)
     5 db = SQLAlchemy()
     6 session_store = Session(app)
     7 
     8 class Config(object):
     9     DEBUG = True
    10     SECRET_KEY = "*(%#4sxcz(^(#$#8423"  # session秘钥
    11     # 数据库连接配置
    12     # SQLALCHEMY_DATABASE_URI = "数据库类型://数据库账号:密码@数据库地址:端口/数据库名称?charset=utf8mb4"
    13     SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    14     # 动态追踪修改设置,如未设置只会提示警告
    15     SQLALCHEMY_TRACK_MODIFICATIONS = True
    16     # 查询时会显示原始SQL语句
    17     SQLALCHEMY_ECHO = False
    18     # 把session通过SQLAlchmey保存到mysql中
    19     SESSION_TYPE = "sqlalchemy" # session类型为sqlalchemy
    20     SESSION_SQLALCHEMY = db     # SQLAlchemy对象
    21     SESSION_SQLALCHEMY_TABLE = 'db_session' # session要保存的表名称
    22     SESSION_PERMANENT = True    # 如果设置为True,则关闭浏览器session就失效
    23     SESSION_USE_SIGNER =  False  # 是否对发送到浏览器上session的cookie值进行加密
    24     SESSION_KEY_PREFIX = "session:" # sessionID的前缀,默认就是 session:
    25 
    26 app.config.from_object(Config)
    27 #SQLAlchemy加载配置项
    28 db.init_app(app)
    29 #Session加载配置项
    30 session_store.init_app(app)
    31 
    32 from flask import session
    33 @app.route("/set")
    34 def set_session():
    35     session["uname"] = "xiaoming"
    36     session["age"]   = 18
    37     return "ok"
    38 
    39 @app.route("/get")
    40 def get_session():
    41     print(session.get("uname"))
    42     print(session.get("age"))
    43     return "ok"
    44 
    45 @app.route("/del")
    46 def del_session():
    47 
    48     print(session.pop("uname"))
    49     print(session.pop("age"))
    50     return "ok"
    51 
    52 if __name__ == '__main__':
    53     with app.app_context():
    54         db.create_all()
    55     app.run()
    View Code

    3.2 redis保存session的基本配置

     这个功能必须确保,服务器必须已经安装了redis而且当前项目虚拟环境中已经安装了redis扩展库

    pip install flask-redis -i https://pypi.douban.com/simple
    # flask-redis是第三方开发者为了方便我们在flask框架中集成redis数据库操作所封装一个redis操作库、
    # 在flask中要基于flask-redis进行数据库则可以完成以下3个步骤即可:
    # 1. 引入flaskRedis并实例化
    from flask_redis import FlaskRedis
    redis = FlaskRedis()
    redis.init_app(app)
    # 2. 在config配置中使用 REDIS_URL配置redis的url地址
    REDIS_URL = "redis://:password@localhost:6379/0"
    
    # 3. 使用实例化后的flaskRedis对象即可操作redis数据库,这个库就是我们之前在django中操作redis时使用库
    # 直接通过 redis对象.命令方法(参数1, 参数2...)
    redis.setex("sms",5 * 60 , "10010")
     1 from flask import Flask
     2 from flask_sqlalchemy import SQLAlchemy
     3 from flask_session import Session
     4 app = Flask(__name__)
     5 db = SQLAlchemy()
     6 session_store = Session(app)
     7 
     8 from flask_redis import FlaskRedis
     9 redis_session = FlaskRedis()
    10 class Config(object):
    11     DEBUG = True
    12     SECRET_KEY = "*(%#4sxcz(^(#$#8423"  # session秘钥
    13     SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    14     SQLALCHEMY_TRACK_MODIFICATIONS = False
    15     SQLALCHEMY_ECHO = False
    16     # redis连接地址  redis://用户名:密码@IP地址:端口/数据库名
    17     REDIS_URL = "redis://:@127.0.0.1:6379/15"
    18     # 把session保存到redis
    19     SESSION_TYPE = "redis"     # session存储方式为redis
    20     SESSION_PERMANENT = False  # 如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效
    21     SESSION_USE_SIGNER = False # 是否对发送到浏览器上session的cookie值进行加密
    22     SESSION_KEY_PREFIX = "session:" # 保存到redis的session数的名称前缀
    23     # session保存数据到redis时启用的链接对象
    24     SESSION_REDIS = redis_session # 用于连接redis的配置
    25 
    26 app.config.from_object(Config)
    27 db.init_app(app)
    28 session_store.init_app(app)
    29 redis_session.init_app(app)
    30 
    31 
    32 from flask import session
    33 @app.route("/set")
    34 def set_session():
    35     session["uname"] = "xiaoming"
    36     session["age"]   = 18
    37     return "ok"
    38 
    39 @app.route("/get")
    40 def get_session():
    41     print(session.get("uname"))
    42     print(session.get("age"))
    43     return "ok"
    44 
    45 @app.route("/del")
    46 def del_session():
    47 
    48     print(session.pop("uname"))
    49     print(session.pop("age"))
    50     return "ok"
    51 
    52 if __name__ == '__main__':
    53     with app.app_context():
    54         db.create_all()
    55     app.run()
    View Code

    四、flask项目配置另一种写法

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_session import Session
    app = Flask(__name__)
    db = SQLAlchemy()
    session_store = Session(app)
    
    from flask_redis import FlaskRedis
    redis_session = FlaskRedis()
    class Config(object):
        DEBUG = True
        SECRET_KEY = "*(%#4sxcz(^(#$#8423"  # session秘钥
        SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
        SQLALCHEMY_TRACK_MODIFICATIONS = False
        SQLALCHEMY_ECHO = False
    
    # 另一种编写flask配置的方式
    app.config.from_object(Config)
    app.config["REDIS_URL"] = "redis://:@127.0.0.1:6379/15"
    app.config["SESSION_TYPE"] = "redis"     # session存储方式为redis
    app.config["SESSION_PERMANENT"] = False  # 如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效
    app.config["SESSION_USE_SIGNER"] = False # 是否对发送到浏览器上session的cookie值进行加密
    app.config["SESSION_KEY_PREFIX"] = "session:" # 保存到redis的session数的名称前缀
    app.config["SESSION_REDIS"] = redis_session # 用于连接redis的配置
    
    db.init_app(app)
    session_store.init_app(app)
    redis_session.init_app(app)
    
    
    from flask import session
    @app.route("/set")
    def set_session():
        session["uname"] = "xiaoming"
        session["age"]   = 18
        return "ok"
    
    @app.route("/get")
    def get_session():
        print(session.get("uname"))
        print(session.get("age"))
        return "ok"
    
    @app.route("/del")
    def del_session():
    
        print(session.pop("uname"))
        print(session.pop("age"))
        return "ok"
    
    if __name__ == '__main__':
        with app.app_context():
            db.create_all()
        app.run()
  • 相关阅读:
    [转]ROS学习笔记十一:ROS中数据的记录与重放
    [转]百度Appollo无人车Perception Module 分析
    百度 Apollo无人车平台增加传感器
    [转]Ubuntu16.04安装搜狗输入法
    [转]Ubuntu16 压缩解压文件命令
    Baidu Apollo use: command " rosbag " not fonud
    nvidia-smi command not found Ubuntu 16.04
    启动Turtlesim,输入roscore命令,报错
    Linux系统下安装Nginx
    linux重启后JDk环境变量配置失效最终解决方案
  • 原文地址:https://www.cnblogs.com/yj0405/p/14826693.html
Copyright © 2020-2023  润新知