• Flask-数据库操作


    一、什么是ORM

    • ORM 全拼Object-Relation Mapping. 称为对象-关系映射
    • 主要实现模型对象到关系数据库数据的映射.
      • 比如:把数据库表中每条记录映射为一个模型对象

    关系映射

    二、Flask-SQLAlchemy安装及设置

    1. 安装

    • 安装 flask-sqlalchemy
    pip install flask-sqlalchemy
    
    • 如果连接的是 mysql 数据库,需要安装 mysqldb
    pip install flask-mysqldb
    

    提示: 如果flask-mysqldb安装不上,推荐安装, pip install pymysql

    2. 数据库连接设置

    • 设置数据库的链接地址,追踪信息
    • 格式:mysql://<用户名>:<密码>@:<端口>/数据库名称
    # 数据库链接地址
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
    # 动态追踪修改设置,如未设置只会提示警告
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    

    查看映射的sql语句,设置: app.config['SQLALCHEMY_ECHO'] = True

    • 配置完成需要去 MySQL 中创建项目所使用的数据库
    $ mysql -uroot -pmysql
    $ create database test charset utf8;
    
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    
    #2.设置数据库的配置信息
    #设置数据库的链接信息,
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
    #该字段增加了大量的开销,会被禁用,建议设置为False
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    
    
    #3.创建sqlalchemy对象db,关联app
    db = SQLAlchemy(app)
    
    # 4.编写模型类,字段,继承自db.Model
    class Student(db.Model):
        __tablename__ = "students"
        #主键, 参数1: 表示id的类型, 参数2: 表示id的约束类型
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32))
    
    @app.route('/')
    def hello_world():
    
        return "helloworld"
    
    if __name__ == '__main__':
    
        #删除继承自db.Model的表
        db.drop_all()
    
        #5.创建数据库的表,创建的是继承自db.Model的表
        db.create_all()
    
        app.run(debug=True)
    

    三、数据库基本操作

    • 在Flask-SQLAlchemy中,插入、修改、删除操作,均由数据库会话管理。
      • 会话用 db.session 表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用 db.session.commit() 方法提交会话。
    • 在 Flask-SQLAlchemy 中,查询操作是通过 query 对象操作数据。
      • 最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询。

    1. 增删改

    """
    增删改
    
    - 全部都是使用db.session操作
    - 常见方法:
      - db.session.add(obj) 添加单个对象
      - db.session.add_all([obj1,obj2]) 添加多个对象
      - db.session.delete(obj) 删除单个对象
      - db.session.commit() 提交会话
      - db.drop_all() 删除继承自db.Model所有表
      - db.create_all() :创建继承自db.Model的所有表
      - 其他:
        - db.session.rollback() 回滚
        - db.session.remove() 移除会话
      - 案例: 编写两个模型类, 一个角色模型类,  还有一个用户模型类
        - 关系: 一对多
    
    """
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    
    #1.设置数据库的配置信息
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    
    #2.创建SQLalchemy对象,关联app
    db = SQLAlchemy(app)
    
    #3.编写模型类
    #角色(一方)
    class Role(db.Model):
        __tablename__ = "roles"
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32))
    
        #如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<Role:%s>"%self.name
    
    #用户(多方)
    class User(db.Model):
        __tablename__ = "users"
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32))
    
        #建立外键
        role_id = db.Column(db.Integer,db.ForeignKey(Role.id))
    
        #如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<User:%s>"%self.name
    
    @app.route('/')
    def hello_world():
    
        return "helloworld"
    
    if __name__ == '__main__':
    
        #为了演示方便,先删除表,后创建
        db.drop_all()
        db.create_all()
    
        app.run(debug=True)
    

    使用ipython进行测试,前提是先进行安装

    2. 查询

    # -*- coding = utf-8 -*-
    # @Time : 2020/10/2 10:15
    # @Author : md
    
    '''
    
    查询练习
    '''
    
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    
    app = Flask(__name__)
    
    
    # 1.设置数据库的配置信息
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    # app.config["SQLALCHEMY_ECHO"] = True
    
    
    # 2.创建SQLalchemy对象,关联app
    db = SQLAlchemy(app)
    
    
    # 3.编写模型类
    # 角色(一方)
    class Role(db.Model):
        __tablename__ = "roles"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
    
        # 关系数据写在这个表中,也就是写在一方这个表中
        # 为了查询方便,不会产生实体字段
        # 给role添加了一个users属性, 那么查询的方式是, role.users
        # 给user添加了一个role属性, 那么查询的方式是, user.role
    
        # 重点 建立关系,这里的名字为想要建立关系的模型名字
        # 解释:前半句话是给Role(本模型)模型添加一个users属性,因为这两个数据库通外键连接
        # 所以,可以通过这个表的对象,就可以访问User表中的数据,例如:查看角色是admin的所有用户role.users
        # 后半句是给本(自己)模型添加一个role属性,这样User表中的对象,就可以访问本表中的数据,可以知道某个用户是什么身份
        # 例如查看用户的身份,user.role
        # lazy="dynamic" 是懒加载
        # backref反向引用
        users = db.relationship("User", backref="role", lazy="dynamic")
    
        # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<Role:%s>" % self.name
    
    
    # 用户(多方)
    class User(db.Model):
        __tablename__ = "users"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
        email = db.Column(db.String(32))
        password = db.Column(db.String(32))
    
        # 建立外键
        role_id = db.Column(db.Integer, db.ForeignKey(Role.id))
    
        # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<User:%s,%s,%s,%s>" % (self.id, self.name, self.email, self.password)
    
    @app.route('/')
    def hello_world():
    
        return "helloworld"
    
    
    if __name__ == '__main__':
    
        # 为了演示方便,先删除表,后创建
        db.drop_all()
        db.create_all()
    
        # 创建测试数据
        ro1 = Role(name='admin')
        db.session.add(ro1)
        db.session.commit()
    
        # 再次插入一条数据
        ro2 = Role(name='user')
        db.session.add(ro2)
        db.session.commit()
    
        # 多条用户数据
        us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
        us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=ro2.id)
        us3 = User(name='chen', email='chen@126.com', password='987654', role_id=ro2.id)
        us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=ro1.id)
        us5 = User(name='tang', email='tang@itheima.com', password='158104', role_id=ro2.id)
        us6 = User(name='wu', email='wu@gmail.com', password='5623514', role_id=ro2.id)
        us7 = User(name='qian', email='qian@gmail.com', password='1543567', role_id=ro1.id)
        us8 = User(name='liu', email='liu@itheima.com', password='867322', role_id=ro1.id)
        us9 = User(name='li', email='li@163.com', password='4526342', role_id=ro2.id)
        us10 = User(name='sun', email='sun@163.com', password='235523', role_id=ro2.id)
        db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
        db.session.commit()
    
        app.run(debug=True)
    
    • 其中realtionship描述了Role和User的关系。
    • 第一个参数为对应参照的类"User"
    • 第二个参数backref为类User,反向引用属性

    第三个参数lazy决定了什么时候SQLALchemy从数据库中加载数据

    • 如果设置为子查询方式(subquery),则会在加载完Role对象后,就立即加载与其关联的对象,这样会让总查询数量减少,但如果返回的条目数量很多,就会比较慢
      • 设置为 subquery 的话,role.users 返回所有数据列表
    • 另外,也可以设置为动态方式(dynamic),这样关联对象会在被使用的时候再进行加载,并且在返回前进行过滤,如果返回的对象数很多,或者未来会变得很多,那最好采用这种方式

    User.query.filter().all()

    3. 查询练习

    查询所有用户数据
    User.query.filter().all()
    此时过滤器可以不写
    User.query.all()
    
    
    查询有多少个用户
    User.query.count()
    
    
    
    查询第1个用户
    User.query.first()
    
    
    查询id为4的用户[3种方式]
    User.query.get(4) 此时get里面是主键
    
     User.query.filter(User.id == 4).all() 返回的是列表,但满足的只有一个
    
    User.query.filter(User.id == 4).first()
    
    User.query.filter_by(id=4).first()
    
    
    
    
    查询名字结尾字符为g的所有数据[开始/结尾/包含]
    User.query.filter(User.name.startswith('g')).all()
    
     User.query.filter(User.name.endswith('g')).all()
    
    User.query.filter(User.name.contains('g')).all()
    
    
    查询名字不等于wang的所有数据
    User.query.filter(User.name != 'wang').all()
    
    
    查询名字和邮箱都以 li 开头的所有数据
    User.query.filter(User.name.startswith('li'),User.email.startswith('li')).all()
    
    
    查询password是 123456 或者 email 以 itheima.com 结尾的所有数据
    from sqlalchemy import or_
    User.query.filter(or_(User.password == '123456',User.email.endswith('itheima.com'))).all()
    
    
    
    查询id为 [1, 3, 5, 7, 9] 的用户列表
    User.query.filter(User.id.in_([1,3,5,7,9])).all()
    
    
    查询name为liu, 的角色数据
    user = User.name.filter(User.name == 'liu').first()
    role = Role.query.filter(Role.id == user.role_id).first()
    
    
    查询所有用户数据,并以邮箱排序
     User.query.order_by(User.email).all()
     User.query.order_by(User.email.desc()).all()
    
    
    
    
    
    每页3个,查询第2页的数据
    
    #page: 表示要查询的页数
    #per_page: 表示每页有多少条数据
    #Error_out: 建议写成False,查不到不会报错
    paginate = User.query.paginate(page,per_page,Error_out)
    
    paginate.pages #总页数
    paginate.page #当前页
    paginate.items #当前的对象列表
    
    
    查询前两条数据
     User.query.limit(2).all()
    
    
    

    lazy="dynamic"

    四、综合案例-图书管理

    目的:

    • 表单创建
    • 数据库操作
    • 一对多关系演练

    实现步骤:

    • 1.创建数据库配置信息,定义模型类
    • 2.创建数据库表,添加测试数据
    • 3.编写html页面,展示数据
    • 4.添加数据
    • 5.删除书籍,删除作者

    1. 图书馆测试数据显示

    • 步骤
      • 1.查询所有作者信息
      • 2.携带作者信息,渲染页面

    2. 图书馆添加数据

    • 添加的逻辑分析:
      • 1.如果作者存在,书籍存在, 不能添加
      • 2.如果作者存在,书籍不存在,可以添加
      • 3.如果作者不存在,可以添加

    3. 图书馆删除书籍

    • 步骤
      • 1.根据书籍编号获取书籍对象
      • 2.删除书籍对象
      • 3.重定向到页面展示

    4. 图书馆删除作者

    • 步骤
      • 1.根据作者编号获取作者对象
      • 2.遍历删除,作者书籍对象
      • 3.删除作者,提交数据库
      • 4.重定向到页面展示

    5. 图书馆CSRFProtect应用

    • 作用: 防止csrf攻击的
    • 使用步骤:
      • 1.导入类CSRFProtect
      • 2.使用CSRFProtect保护app
        • 一旦使用POST,PUT,DELTE,PATCH方式提交的时候就需要校验csrf_token
      • 3.需要设置SECRET_KEY,用来加密csrf_token
      • 4.设置csrf_token到表单中

    6. 表单的创建

    # -*- coding = utf-8 -*-
    # @Time : 2020/10/2 16:07
    # @Author : md
    
    
    from flask import Flask, render_template, request, redirect, flash
    from flask_sqlalchemy import SQLAlchemy
    from flask_wtf.csrf import CSRFProtect
    
    app = Flask(__name__)
    
    # 由于使用了flash,所以得设置
    app.config["SECRET_KEY"] = "wepricsjf"
    
    # 使用 CSRFProtect保护app
    CSRFProtect(app)
    
    
    # 1.设置数据库的配置信息
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    # 生成对应的sql语句在控制台
    # app.config["SQLALCHEMY_ECHO"] = True
    
    
    # 2.创建SQLalchemy对象,关联app
    db = SQLAlchemy(app)
    
    
    # 3.编写模型类
    # 作者(一方)
    class Author(db.Model):
        __tablename__ = "authors"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
    
        # 关系数据,必须有外键为基础
        books = db.relationship("Book", backref="author")
    
        # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<Author:%s>" % self.name
    
    
    # 书籍(多方)
    class Book(db.Model):
        __tablename__ = "books"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
    
        # 建立外键
        author_id = db.Column(db.Integer, db.ForeignKey(Author.id))
    
        # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<Book:%s,%s>" % (self.id, self.name)
    
    
    # 5. 展示数据
    @app.route('/')
    def hello_world():
        # 1. 查询所有的作者信息,因为作者有外键,可以通过关系数据方便的查出该作者对应的书籍
        authors = Author.query.all()
    
        return render_template("library.html", authors=authors)
    
    
    # 6. 添加数据
    @app.route("/add_data", methods=["POST"])
    def add_data():
        # 1. 获取提交的数据
        author_name = request.form.get("author")
        book_name = request.form.get("book")
    
        # 先判断输入的内容是否为空
        if not all([author_name, book_name]):
            flash("作者或书籍不能为空")
            return redirect("/")
    
    
        # 2. 根据作者信息查询作者对象
        author = Author.query.filter(Author.name == author_name).first()
        # 3. 判断作者是否存在
        if author:
            # 4. 通过书籍名称查询书籍对象,并且这本书的作者的id和查询出来的作者的id一样
            # 也就是查看要添加的这本书是不是该作者写的
            book = Book.query.filter(Book.name == book_name, Book.author_id == Author.id).first()
            # 5. 判断书籍是否存在
            if book:
                # return "该作者已经写了这本书了"
                flash("已经有该作者写的这本书了")
            else:
                # 创建书籍对象,添加到数据库
                book = Book(name=book_name, author_id=author.id)
                db.session.add(book)
                db.session.commit()
        else:
            # 作者不存在也是可以添加的
            # 先在作者表中进行添加
            author = Author(name=author_name)
            db.session.add(author)
            db.session.commit()
    
            # 然后再书籍表中进行添加
            book = Book(name=book_name, author_id=author.id)
            db.session.add(book)
            db.session.commit()
    
        # 6. 重定向到首页
        return redirect("/")
    
    
    # 7. 删除书籍
    @app.route("/delete_book/<int:book_id>")
    def delete_book(book_id):
        # 1. 根据id获取到书籍对象
        book = Book.query.get(book_id)
        # 2. 删除这个书籍
        db.session.delete(book)
        db.session.commit()
        # 3. 重定向到页面
        return redirect("/")
    
    
    # 7. 删除作者
    @app.route("/delete_author/<int:author_id>")
    def delete_author(author_id):
        # 1. 根据id获取到作者对象
        author = Author.query.get(author_id)
        # 2. 这个作者的全部书籍,由于使用了关系数据,直接这样写就可以
        books = author.books
        # 3. 遍历这个作者的全部书籍
        for book in books:
            db.session.delete(book)
        # 4. 删除作者
        db.session.delete(author)
        db.session.commit()
    
        # 5. 重定向到页面
        return redirect("/")
    
    
    if __name__ == '__main__':
        # 为了演示方便,先删除后创建
        db.drop_all()
        db.create_all()
    
        # 4. 添加测试数据库
        # 生成数据
        au1 = Author(name='老王')
        au2 = Author(name='老尹')
        au3 = Author(name='老刘')
        # 把数据提交给用户会话
        db.session.add_all([au1, au2, au3])
        # 提交会话
        db.session.commit()
    
        bk1 = Book(name='老王回忆录', author_id=au1.id)
        bk2 = Book(name='我读书少,你别骗我', author_id=au1.id)
        bk3 = Book(name='如何才能让自己更骚', author_id=au2.id)
        bk4 = Book(name='怎样征服美丽少女', author_id=au3.id)
        bk5 = Book(name='如何征服英俊少男', author_id=au3.id)
        # 把数据提交给用户会话
        db.session.add_all([bk1, bk2, bk3, bk4, bk5])
        # 提交会话
        db.session.commit()
    
        app.run()
    

    7. library.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    {# action: 提交到的地址, method: 表示提交的方式 #}
    <form action="/add_data" method="post">
    {# 设置隐藏字段csrf_token , 只要使用了CSRFProtect,然后使用模板渲染的时候就可以直接使用csrf_token()方法#}
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
    
        作者: <input type="text" name="author"><br>
        书籍: <input type="text" name="book"><br>
        <input type="submit" value="添加"><br>
        {% for message in get_flashed_messages() %}
            <span style="color: red;">{{ message }}</span>
        {% endfor %}
    </form>
    
    <hr>
    
    {# 数据展示 #}
    <ul>
        {# 遍历作者 #}
        {% for author in authors %}
    {#        <li>作者: {{ author.name }}</li>#}
    {#        <li>作者: {{ author.name }} <a href="/delete_author/{{ author.id }}">删除</a></li>#}
            <li>作者: {{ author.name }} <a href="{{ url_for("delete_author",author_id=author.id) }}">删除</a></li>
    
            {# 遍历作者的书籍 #}
            <ul>
                {% for book in author.books %}
    {#                <li>书籍: {{ book.name }} </li>#}
                    <li>书籍: {{ book.name }} <a href="/delete_book/{{ book.id }}">删除</a></li>
                {% endfor %}
    
            </ul>
        {% endfor %}
    
    </ul>
    
    
    
    </body>
    </html>
    

    五、多对多

    在项目开发过程中,会遇到很多数据之间多对多关系的情况,比如:

    • 学生网上选课(学生和课程)
    • 老师与其授课的班级(老师和班级)
    • 用户与其收藏的新闻(用户和新闻)
    • 等等...

    所以在开发过程中需要使用 ORM 模型将表与表的多对多关联关系使用代码描述出来。多对多关系描述有一个唯一的点就是:需要添加一张单独的表去记录两张表之间的对应关系

    1. 需求分析

    • 学生可以网上选课,学生有多个,课程也有多个
    • 学生有:张三、李四、王五
    • 课程有:物理、化学、生物
    • 选修关系有:
      • 张三选修了化学和生物
      • 李四选修了化学
      • 王五选修了物理、化学和生物

    需求:

    1. 查询某个学生选修了哪些课程
    2. 查询某个课程都有哪些学生选择

    2. 代码

    # -*- coding = utf-8 -*-
    # @Time : 2020/10/2 19:30
    # @Author : md
    
    
    '''
    多对多,学生和课程
    '''
    
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    
    app = Flask(__name__)
    
    
    # 1.设置数据库的配置信息
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/test"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    # app.config["SQLALCHEMY_ECHO"] = True
    
    
    # 2.创建SQLalchemy对象,关联app
    db = SQLAlchemy(app)
    
    
    # 3.编写模型类
    # 学生
    class Student(db.Model):
        __tablename__ = "students"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
    
        # 关系数据,使用在多对多中的时候注意secondary这个属性,是中间表的表名,用来二次查询
        courses = db.relationship("Course", backref="students", secondary="td_student_course")
    
        # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<Role:%s>" % self.name
    
    
    # 课程
    class Course(db.Model):
        __tablename__ = "courses"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
    
        # 如果一个类继承自object那么重写__str__方法即可, 如果是继承自db.Model那么需要重写__repr__方法
        def __repr__(self):
            return "<User:%s>" % self.name
    
    
    # 中间表
    db.Table(
        "td_student_course",
        db.Column("student_id", db.Integer, db.ForeignKey(Student.id)),
        db.Column("course_id", db.Integer, db.ForeignKey(Course.id))
    )
    
    @app.route('/')
    def hello_world():
    
        return "helloworld"
    
    
    
    # 为了演示,先删除后创建
    db.drop_all()
    db.create_all()
    
    stu1 = Student(name='张三')
    stu2 = Student(name='李四')
    stu3 = Student(name='王五')
    
    cou1 = Course(name='物理')
    cou2 = Course(name='化学')
    cou3 = Course(name='生物')
    
    stu1.courses = [cou2, cou3]
    stu2.courses = [cou2]
    stu3.courses = [cou1, cou2, cou3]
    
    db.session.add_all([stu1, stu2, stu2])
    db.session.add_all([cou1, cou2, cou3])
    
    db.session.commit()
    
    
    if __name__ == '__main__':
        app.run()
    
    

    六、数据库迁移

    • 目的: 当数据库的表结构发生变化之后,如果直接删除原有的数据,再添加新的数据,有可能导致数据丢失
    • 注意点:
      • 1.是为了备份表结构,而不是数据
      • 2.如果想要备份数据,需要使用工具,navicat,mysqlworkbench,等等
      • 3.更新的过程数据一般不会丢失,做降级的时候需要谨慎操作
    • 操作流程:
      • 1.安装扩展
        • pip install flask_script
        • pip install flask_migrate
      • 2.导入三个类
        • from flask_script import Manager
        • from flask_migrate import Migrate, MigrateCommand
      • 3.通过Manager类创建对象manager,管理app
        • manager = Manager(app)
      • 4.使用Migrate,关联db,app
        • Migrate(app,db)
      • 5.给manager添加一条操作命令
        • manager.add_command("db",MigrateCommand)
      • 相关迁移命令:
        • 生成迁移文件夹[一次就好]
          • python xxx.py db init
        • 将模型类生成迁移脚本[重复执行]
          • python xxx.py db migrate -m '注释'
        • 将迁移脚本更新到数据库中[重复执行]
          • python xxx.py db upgrade/downgrade [version]
        • 其他命令
          • 查看最新版本的命令
            • python xxx.py db show
          • 查看当前版本
            • python xxx.py db current
          • 查看所有的历史版本
            • python xxx.py db history
    # -*- coding = utf-8 -*-
    # @Time : 2020/10/2 20:38
    # @Author : md
    
    from flask import Flask
    from flask_script import Manager
    from flask_migrate import Migrate, MigrateCommand
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    
    # 设置数据库配置信息
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@localhost:3306/test1"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    
    # 创建SQLAlchemy对象,关联app
    db = SQLAlchemy(app)
    
    
    # 3. 通过Manager类创建对象manager,管理app
    manager = Manager(app)
    
    # 4.使用Migrate,关联db,app
    Migrate(app, db)
    
    # 5.给manager添加一条操作命令
    manager.add_command("db", MigrateCommand)
    
    
    # 6.编写模型类
    class Student(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(32))
        age = db.Column(db.Integer)
       # email = db.Column(db.String(32))
    
    
    @app.route('/')
    def hello_world():
        return "helloworld"
    
    
    if __name__ == '__main__':
        manager.run()
    

    生成迁移文件夹

    将模型类生成迁移脚本

    将迁移脚本更新到数据库中

    此时就可以在数据库中看到对应的表了

    此时在代码中多写一行,添加一列

    然后继续执行这两条命令,就会看到数据表结构中就多了一列

    还可以进行降级

    然后再升级到指定的版本

  • 相关阅读:
    wiki iso88591字符表的解释
    [c]字符1一维数组求长度
    vim 用户配置
    PHP中向浏览器输出图片
    如何及时取消 BackgroundWorker 组件的后台工作
    python basic
    php5.1中的时区设置。
    MyBatis的深入原理分析之1架构设计以及实例分析
    hibernate缓存:一级缓存和二级缓存
    Spring 注解(Annotation)代替XML实现零配置
  • 原文地址:https://www.cnblogs.com/mengd/p/13820764.html
Copyright © 2020-2023  润新知